Live-templates - connect a front-end template to a LiveState phoenix channel

live-templates is a library that allows you to drop a template into a static html website that will be connected to a LiveState phoenix channel on the backend. It eliminates the need to develop a custom element (or any other javascript) to build simple LiveState based applications. This is the very first release, so it’s early times, but it is far enough along to prove that the idea is viable and get deployed examples working. I’d love community feedback. This obviously overlaps with LiveView, but uses a somewhat different approach which makes it likely a better fit for cases such as static html websites or PWAs.

8 Likes

I think LiveState is a very cool part of this approach.

I’ve considered that it could be possible to drive an entire PWA using LiveState to avoid a graphql intermediate layer with a simple router/state manager in the front end with some custom elements.

My thoughts in respect of LiveTemplate is that you could consider separating the concerns using Lit Controller for reactive state management and fetching state via LiveState and then render named and registered reactive custom elements via LiveComponents and regular Phoenix function components. What these components would render as part of the app js bundle is a Lit based custom element or template that receive their state as props from the LitController on the front end. This keeps it aligned with the LiveState / LiveComponent / functional component state management concept.

There would be some considerations for Heex template rendering to lit element templates but this approach could even support SSR via Declarative Shadow DOM.

I think LiveTemplate is a good start but the destination could be another world that is currently off limits to Phoenix server based approach.

This all looks very doable and would open the door to Phoenix PWA’s, with Phoenix SSR rendering and no need for a node based backend to support SSR given the source of truth is Elixir code which can do server rendering just fine. The missing link to this world is literally LiveState (done), LiveState Lit Controller (partially done with LiveTemplate), Lit Template (not done), Lit Element Wrapper (not done).

Those are interesting thoughts. I’m definitely a fan of Lit, but my goal with LiveState and by extension, live-templates is to keep as close as I can to web standards and avoid coupling to any particular implementation (eg Lit) as much as I can. This influenced my thoughts on template implementation as well. Though they are still developing, there are a couple of standards, template instantiation and DOM parts, that are making their way through the standards process and which the template library I chose is based on. This should make it pretty straightforward to swap out if I needed to, and to ditch altogether if templating makes it all the way into the browser.

As far as what you are talking about with heex rendering into lit element templates, this sounds a bit like the idea I was exploring that initially led me to create LiveState in the first place. I initially attempted to get Liveview to render into a custom element. I got some basic examples working with a greatly hacked version of Liveview, but it quickly became clear that it would require something close to a rewrite of Liveview for it to work. In a way, if you squint really hard, you can think of live-template as the very beginning of a possible reimagining or reimplemenation of Liveview, though it is much too soon to say how far it will get.

All that said though, I would absolutely welcome contributions. It is also quite possible I didn’t understand all your ideas, and sometimes seeing things in code makes is easier (at least for me) to grok than words.

2 Likes

Oh, and on the subject of PWA: on the next examples I plan to build is a PWA, I’ll add that to the README when I do.

2 Likes

The rendering in Lit uses JavaScript template literals which are available in all modern broswers and part of the Ecmascript specification so it’s not coupled to Lit. My understanding is that Lit has deliberately focused on being web standards based and specifically not inventing custom things like DSLs which Stencil does.

So to clarify my earlier idea, what I actually meant is translating Heex to a JavaScript template literal tagged as html (which is all Lit does) as the more succinct objective to produce reactive custom elements from Phoenix.

There are two rendering paths, one on the server which I am suggesting can emit html using declarative shadow DOM which relies on html templates and is currently in standardization with a polyfil for browsers that don’t have it yet.

I honestly believe with these pieces in place this should be the default rendering approach in a future version of Phoenix. Almost everything should be rendered as a html reactive custom element which would provide scoped styles and eliminate the hooks as any style and JS can be co-located with the custom element which could be rendered via function component or a LiveComponent.

If Phoenix has no intention of taking this approach then I think we have just conceived a new elixir web framework based on existing web standards (and soon to be standards) which will open the doors to the new world of embeddable Elixir components and PWAs.

This was my first thought as well, but unfortunately it doesn’t quite turn out to be as simple as that. What I set out to do (and others have as well) is to allow an html author to define their own template in html. In order for this to work, you need to somehow grab the template out of html and evaluate it. This would require you dynamically build a template literal at runtime, which is sadly not a thing AFAIK.

As I mentioned, others have been working on this, including Justin Fagnani one of the main Lit contributors. He came up with Stampino but it has not been maintained. My first template approach was to use a forked version of Stampino. I ran into an issue I thought was with Stampino that in the end was not really a Stampino issue at all, but I had switched to templize already and just kept rolling.

For additional context, here are the Template Instantiation and DOM Parts specs. I think its likely some version of these will emerge that will be the standards based solution, for now there are several “prollyfill” implementations worth checking out.

1 Like

Thanks for those links,

I sure hope the Apple/Ember approach does not emerge as an unnecessary complexity monster based on their Ember complexity mindset.

The DOMparts approach is reasonably sensible.

The upside on all of this is that the performance of DOM updates based on templates and parts will improve whether it’s for web componnents or the way Phoenix currently does DOM updates.

Nothing is preventing the use of custom elements today as a way to improve the way our Elixir server rendered applications work and increase the use cases to embeddable components, scoped styles and colocated JS (no more hooks), and Phoenix PWAs.

Today it is doable to package templates, styles and js into custom elements for co-locating concerns benefiting from the shadow DOM isolation. There are many custom element support libraries.

To make this work someone has to pick a support library such as Lit but it’s nothing new, we always have to pick supporting tools to make things work and these will melt away as standards are adopted.

What we don’t have yet is some of the glue as I have described to make custom elements a first class default approach to rendering and bundling style and JS in Elixir plug based web apps.

I probably need to start with the ~WC sigil for rendering web components.

With you on that, I still have PTSD from the last time I used Ember :slight_smile:

This actually sounds quite interesting, I think when I realized I’d need a new kind of sigil is about when i bailed. It for sure seems worth exploring though. Do let me know if you get anything going, happy to help out if i can.

It almost destroyed me too, and I am not exaggerating. I basically avoided any commercial software development for 7 years after a failed Ember project and started consulting. I was burnt out and just couldn’t stomach anything to do with the web development ecosystem any more.

Just published version 0.0.2. Notable new feature: your template can live inside a <template> element inside <live-template>. Because template elements are inert, this will avoid early rendering and allow you to have content that displays before connection is established. For example:

<live-template>
  <template>here is a {{thing}} thats get rendered when connected</template>
  <div>this is what will be rendered before connection</div>
</live-template>
1 Like

@superchris this is very cool!

2 Likes

New version shipped as 0.4.0. Notably additions include:

  • Upgraded to Sprae 9.0.1
  • Declarative event sending eg <button :sendclick="foo"> instead of <button :onclick="sendEvent('foo'">
  • Fully worked CRUD example

Next goal: client side navigation.

4 Likes