mholt 2 days ago

I'm using the <template> tag heavily in Timelinize[0], which has a fairly sophisticated UI that I'm writing in vanilla JS -- not even jQuery. I use a few libraries (for mapping, datetime, and Bootstrap+Tabler for some nice styles), but that's it.

I wrote some boilerplate JS, yes, but I have complete control over my frontend, and I understand how it works, and I don't need to compile it.

Anyway, it works well so far! The <template> tag is a great way to lay out components and then fill them in with simple JS functions.

One nuance is documented in my code comments:

    // Ohhhhhh wow, we need to use firstElementChild when cloning the content of a template tag (!!!!):
    // https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/template#avoiding_documentfragment_pitfalls
    // I spent way too long on this.
    const elem = $(tplSelector);
    if (!elem) return;
    return elem.content.firstElementChild.cloneNode(true);
Once I figured that out, it's been smooth sailing and very powerful.

Oh, but I haven't cleaned up my code at all yet because I was just experimenting/hustling, so it's a bit spaghetti :) If you go looking, don't mind the mess.

---

[0]: https://github.com/timelinize/timelinize - a self-hosted application for bringing together all your data on your own computer and organizing it onto a single timeline: social media accounts, photo libraries, text messages, GPS tracks, browsing history, and more. Almost ready for its debut...

  • jfagnani 2 days ago

    You should use document.importNode() to clone templates.

    Template contents are in a separate document from the main document, which is what makes them inert. importNode() adopts the nodes into the document so they have the correct prototype immediately (which includes custom elements). Otherwise the adopt steps are run when the elements are first attached to the document, which adds another tree walk to the insert/append operation that costs some time.

    So:

        document.importNode(elem.content, true);
    
    Then you'll have a DocumentFragment you can pull nodes out of. Or just append the whole fragment.
    • mholt 2 days ago

      Awesome -- gonna try this. Thanks for the tip! And lit-html looks cool btw.

      Update: I'm using importNode() now -- works great too.

  • mikae1 2 days ago

    Timelinize, just wow. Been wishing for something like this forever. Love the idea!

    Regarding the gpx support... Don't want to lead you astray, but, have you seen https://www.sethoscope.net/heatmap/?

    • mholt 2 days ago

      Thanks! Hopefully it delivers.

      I haven't seen that, actually -- looks very nice. We do render a heatmap already, but I'm learning that heatmaps are very tricky to tune to be most useful/interesting. I will try to learn from that project.

  • mariusor 2 days ago

    I considered vanilla template initially for building my ActivityPub frontend[1], but in the end the sugar that lit-js adds on top of web components seemed worth the file size overhead.

    [1] https://github.com/mariusor/oni

    • jfagnani 2 days ago

      Author of lit-html here.

      Yeah, Lit's tagged template literals and render() method are basically a shorthand for making a <template> element, marking the spots where expressions go, cloning the template, then filling in those sports.

  • WorldMaker a day ago

    > I use a few libraries (for mapping, datetime

    I'm really looking forward to Temporal [0] reaching a larger baseline. Between that and a lot of recent Intl pieces we are so close to not needing libraries for much of anything datetime related.

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...

    • mholt a day ago

      Yeah, dealing with date/time in JS has been a HUGE pain. I haven't tried Temporal yet but I hope it's better.

      • WorldMaker 19 hours ago

        I've used it a bit already. You can use it with an experimental flag in Deno. It takes a lot of inspiration (from among others) from the java.time library added in Java 8+ in a similar way that JS' original Date class is related to the very original Java Date class, so it basically catches up on 8+ versions of Java.

        It supports just about all the Date math, comparison, and calendar conversion you could ever want. It has nice toLocaleString() formatting options. It's built on immutable objects to avoid a whole class of bugs with the current JS Date.

  • freedomben 2 days ago

    Dude, cool project! I considered building something like this a couple years ago as the only way in hell I'd ever use it is if it's open source and self-hosted (thanks so much for using AGPLv3!). I ended up stuck in analysis paralysis, so I'm super impressed :-)

    • mholt 2 days ago

      Ha, thanks. It's hard, so no shame for being "stuck". I've iterated on this for over a decade at this point. Still more evolution to come... but I really want this for my family.

  • Lord_Zero 2 days ago

    What's Tabler?

    • mholt 2 days ago

      It's this: https://tabler.io/admin-template

      Still highly unstable between versions, but for being free, it looks really good and is very flexible. I've been pleased with it for this project.

      • WorldMaker a day ago

        Seems to me a lot of what Tabler does you could do easily today in "vanilla" CSS Grid, which is also even more flexible. (I have done some very dynamic dashboards with simple CSS class changes and CSS Grid. You can do so much just changing grid-template-areas, and I really like its feel as an ASCII diagram of the layout that you want so I think it's also easy to scan a lot of layout variations in a CSS file to see which one is which.)

        At this point I've been ditching almost every other type of layout (Bootstrap's Grid, Flexbox, etc) in most places for just "vanilla" CSS Grid and I think it is fantastic. I think it is well worth learning if you haven't yet.

        • mholt a day ago

          I use grid (still find it hard to grok though) -- but Tabler is more than just layout/flow. I like Tabler's component styles and it's highly customizable and easy to use, which I appreciate.

  • cyanydeez 2 days ago

    It's almost guaranteed this will be used for unwanted surveillance.

    • mholt 2 days ago

      It doesn't actually get any of your data, let alone anyone else's. It's just an organizer, so please elaborate.

jjcm 2 days ago

Templates are solid and are slightly more performant than including your html-in-js for webcomponents, but that said I really wish there was some sort of web component file format that incorporated:

- The HTML

- The JS

- The CSS

In some sort of a structured way that's easy to load and distribute as a library. I don't like that to use webcomponents the right way, you have to load the logic from an import and then inline the html aspects of it.

  • jfagnani 2 days ago

    There is a spec issue open for HTML Modules [1] along with a few proposals. The concept needs some motivated champions to see it through. Microsoft has shown some interested in this lately.

    There are userland single-file component projects, like my Heximal[2] project. Though Hexiaml specifically doesn't tackle the module format - it requires some kind of HTML Module polyfill.

    I don't think the current situation is so bad though. The container format should mostly be irrelevant to consumers of a component. You need to import the component defintion whether that definition is in a .js file or .html file. Once you import it you use it the same.

    There should be very few cases where the file format matters. Maybe for use when JS is turned off if HTML-based web components are considered safe to evaluate (their templates might expressive enough to potentially allow attacks).

    [1]: https://github.com/WICG/webcomponents/issues/645

    [2]: https://heximal.dev/ (Sorry the site is messed up on mobile. I need to fix it!)

    • epolanski 2 days ago

      Not gonna lie, I like the design of heximal, but by the end of reading the docs I start missing simple php-like templating.

  • marcosdumay 2 days ago

    Well, turns out you can just add style tags to the template, and they will be scoped there. It's the only way to get local CSS rules.

    You can also add script tags wherever you want. They will execute when added to the DOM, but they won't be scoped.

    • spankalee 2 days ago

      Styles aren't scoped to templates.

      You might be thinking of shadow DOM: if you clone your template into a ShadowRoot, then any included styles will be scoped to that ShadowRoot.

  • dexwiz 2 days ago

    Salesforce actually had a really nice module format called LWC that does that. Also supports one way binding. Too bad they never championed outside of customer use.

mvdtnz 2 days ago

Reading the first example I'm not really seeing what gains I get from this. It's just as much work to create a table row using the template as doing it from scratch.

  • anaisbetts 2 days ago

    Of course, the goal of the example is to teach using an example that makes sense logically. Templates can be arbitrarily large and obviously as the template gets bigger, the difference between it and manual `document.createElement` calls gets much larger.

    • rendaw a day ago

      The difference in what? TBH I don't get the purpose either. You have to use javascript either way, and it's trivial to do make a shorthand for `document.createElement` that sets properties and adds children... maybe 10 lines per project.

      I thought it was an optimization, but benchmarking `document.createElement` was significantly faster (firefox).

      And then having `template` in your html means that changes to the template/use are less local.

      I feel like this is an improvement that only makes sense if you're neck deep in the react world.

      • WorldMaker a day ago

        The React world is still deep in `document.createElement` and doesn't seem to be investing in the template tag any time soon.

        I don't know what your benchmarks were exactly, but my benchmarking (also primarily in firefox) shows cloning templates is much faster than `document.createElement` for many tree shapes I was encountering. (Not micro-benchmarks of one element or so at a time, but the tree contents of entire components and "pages" at a time.) That's before learning of a performance tweak I'd missed from reading this thread today (`document.importNode` for template contents cloning to avoid multiple tree walking passes to attach the clone to the document).

  • epolanski 2 days ago

    Can't understand the point of a react/Vue hello world either, they are more verbose than just writing the html.

  • Spivak 2 days ago

    I agree, this seems more complicated than just defining your template in JS. You have to use JS to interact with them anyway and it's basically a mapping between some well-known strings and a factory to create a DOM node except less flexible. The advantage seems to be only if you don't interact with your templates in JS and use them inline in your HTML.

  • phartenfeller 2 days ago

    Think of a large template with many attributes like classes and structure. When you want to render this multiple times you just have to update a few things for the unique instance instead of recreating the structure and classes over and over.

    • palmfacehn a day ago

      This, and separation of concerns. HTML stays in HTML or your preferred SSR template where it belongs.

      Another reason I like <template> is the ease of prototyping. A very straightforward approach is to mock up your HTML+CSS with placeholders of what your populated elements might look like. Instead of translating that into JS element generation code, you can simply remove the populated data and enclose the barebones element in a <template> tag.

      Back in JS, you might have a simple initializer to add these elements as needed and a function to (re)populate them.

      Simple, to the point and no libraries or frameworks required.

  • dexwiz 2 days ago

    I think it's designed more for web components.

tmalsburg2 a day ago

What problem is this trying to solve and does it actually succeed at solving it? I‘m struggling to see the appeal given that the JS still needs to model the internal structure of the template in order to fill the slots.

  • WorldMaker a day ago

    The Shadow DOM can auto-fill the slots in the case where a web component has slot fillers in the main DOM. You still need JS to invoke/create the shadow DOM, but in that case your JS might be minimal and not need to model the interior structure.

    But the big problem that template tries to solve is building DOM fragments that are parsed but not "live" in the open documment. Before the template tag there was no good way to do that other than JS and createElement/createElementNS, and that has always been slower than the Browser's well optimized HTML parser.

    Also, the slot tag does solve a minor problem of being the first tag whose out-of-the-box (browser CSS) behavior is `display: contents;`. It's obviously not a huge lift from the CSS one-liner, but there are still some uses for it even outside of templates.

blittle 2 days ago

Shopify heavily uses <template> elements with their Storefront Web Components project, except the templates themselves are passed as a child to the web component, that dynamically queries the data necessary to render the template, before mounting the element to the DOM: https://shopify.dev/docs/api/storefront-web-components

nozzlegear 2 days ago

I've been using template elements a lot recently to render products on my wife's photography blog. The product data gets loaded from a headless MedusaJS instance, plugged into a template that matches her blog's theme, and then dropped into the page. I specifically wanted to avoid reaching for something like React since the page load is already pretty heavy with the size of her images. Template's been pretty easy to use in that respect.

  • nine_k 2 days ago

    Frankly, preact is 4 kB, should be peanuts comparing to any image.

    • nozzlegear 16 hours ago

      I hadn't considered Preact, I always forget about it honestly. That could be a good compromise. Cheers!

EGreg 2 days ago

What exactly is the point of <template> tag? Just to create document fragments? I mean that’s all you can really do with it in HTML. If you are using JS you can attach shadow dom to any element.

I guess maybe slots for web components is the other point?

  • acdha 2 days ago

    I’ve used it to have the server generate fragments not processed in the normal page load which are then used as templates by JavaScript which populates them. That supported fast initial page loads compared to an SPA while being just as dynamic after being loaded.

    This worked pretty well but definitely had some rough edges which I really wish the standards process could’ve focused on. Things like JSX are so much slower / memory intensive but people use them for convenience and it’d be nice to improve the ease-of-use story.

    • mikojan a day ago

      Could you not achieve the same with a <div hidden>?

  • dspillett 2 days ago

    > Just to create document fragments?

    Largely, I think. Though I've not got around to actually using them yet myself, so take my understanding with a pinch of salt.

    Compared to doing that with non-displayed HTML tags outside a template there are performance benefits (the parser deals with it differently knowing it isn't intended to be an active bit of DOM yet) and convenience benefits (IIRC the contents are not going to be picked up by querySelector/querySelectorAll).

    Compared to building document fragments in JS they can be a lot more convenient to create and edit, and keep your design and code less tightly coupled (so a designer on your team who doesn't want to touch JS (or who you don't want messing with your JS!) can easily play with them to a certain extent). Other methods to achieve the same separation may involve an extra build step in deploying your work.

  • 65 2 days ago

    Alpine.js uses <template> tags for if statements and for loops with stateful data. E.g. <template x-if="myVariable === 1"><div>1</div></template>

    Which is a simpler way of thinking about templates, rather than slots and fragments.

    • EGreg a day ago

      Why not just use handlebars js?

  • Theodores 2 days ago

    Good question. Yes there was all that web components stuff that didn't go the HTML5 way, and the template element is definitely a child of that. Since elements that get into the spec can't be removed easily, they do get repurposed instead over time.

alserio 2 days ago

I was wondering, are template elements a good place to store json data in the page to be consumed by js?

  • jfagnani 2 days ago

    No. I would use <script type="-json">

    <script> parses its contents as text, whereas <template> parses as DOM. This means you don't have to escape `<`, just `</script>`.

    Myself and some browser engineers been working on proposals to allow for inline modules, including JSON, that are importable into other modules via regular import statements.

    This is why I recommend the "-json" type - so it doesn't collide with a future native "json" type.

    • SahAssar 2 days ago

      Why not use a somewhat proper mime type like `<script type="application/mytype+json">` or similar? Seems like your suggestion is not what the spec recommends: https://html.spec.whatwg.org/multipage/scripting.html#attr-s...

      • jfagnani 2 days ago

        My understanding is that in implementations any unknown type creates a "data block", which is just unprocessed text.'

        I wouldn't use application/json just in case browsers start supporting that and it has different semantics than whatever custom thing you might do, causing a webcompat issue when the native feature rolls out.

        Although with JSON, it's pretty unlikely that there would be any differing semantics. JSON modules in JS are just JSON blocks with no special additions and no named exports. That's what inline versions would be as well.

        • SahAssar 2 days ago

          But wouldn't a subtype like `mytype` in my example (`application/mytype+json`) still be be a valid mime-type and still avoid your concerns? I've used these before.

    • alserio 2 days ago

      Thank you. And that proposal seems really interesting. Can I ask for a link if you happen to have one publicly accessible?

  • bsmth 2 days ago

    You might be interested in data attributes for this use case https://developer.mozilla.org/en-US/docs/Web/HTML/How_to/Use... although it depends on the shape of the JSON data you had in mind.

    • alserio 2 days ago

      What do you mean with shape? Are you concerned about escaping and such?

      • bsmth 2 days ago

        I can imagine if it's deeply nested data, your markup might get complex, but the structure of the HTML doesn't have to mirror the JSON. There's other examples here which might illustrate more how this can look: https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/...

        • alserio 2 days ago

          Thank you. I was looking at a generic way to pass configuration data to custom elements where I cannot know the shape in advance, since another dev can have different requirements. I support data attributes for simple types but i was wondering if allowing arbitraty json objects via other means could be feasible.

          • hunter2_ 2 days ago

            Since JSON is a subset of JavaScript, you can just use a script element, and including the json mime type certainly doesn't hurt:

                <script type="application/json" id="myJSONData">
                  {
                    "name": "John Doe",
                    "age": 30
                  }
                </script>
            
                <script>
                  const data = JSON.parse(document.getElementById('myJSONData').textContent);
                  console.log(data.name + " is " + data.age); // John Doe is 30
                </script>
            
            Note: The JSON data must exist literally within the script element. If you try using a src attribute to request it from elsewhere, the response will not be available via textContent or any other mechanism [0], and at that point you just need to fetch/ajax/xhr it.

            [0] https://stackoverflow.com/questions/17124713/read-response-o...

            • lioeters 2 days ago

              About embedding JSON in a script tag, I recently read an article on the risk of a closing </script> tag within the JSON that could break it.

              Safe JSON in script tags: How not to break a site - https://sirre.al/2025/08/06/safe-json-in-script-tags-how-not...

              As with all untrusted content, depending on where the JSON string comes from, sanitizing the output is worth considering.

              • yencabulator 7 hours ago

                That article was pretty complicated; I appreciate the historical understanding but frankly web legacy is too complex to bother with "why" too much, in the end so many things just don't make sense and are historical accidents.

                Here's another take, just a short list of replacements. Interestingly, "&" is also escaped: https://pkg.go.dev/encoding/json#HTMLEscape

                • lioeters 5 hours ago

                  That's a helpful summary of what's necessary to make JSON safe to embed in script tags.

                  I agree the "why" is too long of a story, an accumulation of supposedly logical decisions that led up to the ball of quirks. It's too much to remember. Exactly the kind of thing that should be delegated to a specialized function made and maintained by experts.

              • hunter2_ a day ago

                Great article! I suppose a similar (yet different) precaution would be needed in data-* attributes or any other part of an HTML document.

  • yuchi 2 days ago

    As good as a script element with type application/json.

    • joeframbach 2 days ago

      I wonder if the browser would attempt to validate the contents of a script tag with type json, versus treating it as a blob that would only be validated when parsed/used. And any performance overhead at load time for doing so. Not at a machine at the moment so I can't verify.

    • alserio 2 days ago

      well one difference is that application/json scripts are still subject to CSP policies

      • unilynx 2 days ago

        How so? I don't remember ever having seen issues with this. If anything CSP steers you towards this (instead of inline scripts directly assigning to JS variables)

        • alserio 2 days ago

          I thought I knew but it seems that the CSP story is unclear. I couldn't find an authoritative source for either position

          • SahAssar 2 days ago

            CSP blocks execution/inclusion, but since json does not execute and any json mimetype will not do execution there is no problem.

            Any CSP-allowed other script can read that application/json script tag and decode it, but it is no different than reading any other data it has access to like any other html element or attribute.

            • alserio 2 days ago

              That makes sense, thank you

  • Gualdrapo 2 days ago

    For my portfolio (miler.codeberg.page) and the refactor&redesign I'm doing of it (that I hope to finish soon!), I feed some <template>s with data coming from a json that acts like kind of a database. I feel the process of querying nodes and setting their data is still a bit rudimentary in plain JS and it should be a pain in the ass for huge datasets or lots of nodes, but at least with modern JS it is not necessary to fetch the json with a XMLHTTPRequest or something - it can work importing it like a regular JS module, so at least there's that.

imiric 2 days ago

There is untapped potential for building modern web sites by leveraging standard web technologies, such as the template element, and sidestepping a whole bunch of bloated abstractions that plague most modern web frameworks. Essentially, we need the simplicity of old school web development married with modern web features.

There are a few modern libraries and frameworks that trend in this direction: Nue, Datastar, Lit. The DX and UX with these is a breath of fresh air.

I've experimented with this approach myself with Miu[1]. It doesn't quite integrate with Web Components nicely yet, but it's almost there. I have some bones to pick with the WC standard, but that's a separate matter.

My wish is that modern web development can eventually not require any 3rd party libraries or frameworks, just like in the early days. Web developers got used to these because of limitations of native web APIs, but the web has grown leaps and bounds since then. Before the modern workflow became standard, it was magical to open a text editor, and have a functioning web page within a few minutes. No dependencies, no build step, no nonsense. Let's bring that back, please.

[1]: https://github.com/hackfixme/miu

  • jfagnani 2 days ago

    I wrote a couple of blog posts on why we should add native templating to the DOM so we'd need fewer libraries.

    The time is right for a DOM templating API: https://justinfagnani.com/2025/06/26/the-time-is-right-for-a...

    What should a native DOM templating API look like?: https://justinfagnani.com/2025/06/30/what-should-a-dom-templ...

    • quectophoton 2 days ago

      I would be very interested in an API similar to the plates[1] library, but with support for event bindings (instead of being just a one-off rendering of plain HTML). My first thought is that it might not be very maintainable, and at best might only be useful for small templates or templates that are heavy on microdata[2].

      But there's just something about this type of binding that makes me want to give it a serious chance, at least once, before completely giving up on it.

      [1]: https://github.com/flatiron/plates

      [2]: https://developer.mozilla.org/en-US/docs/Web/HTML/Guides/Mic...

      • jfagnani 2 days ago

        Plates style isn't what developers expect from modern templating syntaxes. Every popular syntax today supports inline expressions.

    • imiric a day ago

      I skimmed through your blog posts, and the WICG proposal, and my main objection to it is making it depend on JavaScript.

      There are plenty of ways HTML templating can be done already using JavaScript. The simplest approach of using tagged template literals, as you mention, doesn't even require external dependencies.

      The problem with this approach is that it makes JavaScript a requirement for all but static sites, and those doing templating on the server. This shouldn't be the case.

      The web as a platform should be flexible, and provide tools to build maintainable web sites and applications without forcing developers and users to depend on a specific runtime. JS should be an optional dependency, just like CSS is today. Even HTML should be optional, as Web Assembly gains traction, and the web browser becomes a software delivery platform.

      Furthermore, making what should be a core HTML feature depend on JS is a colossal violation of separation of concerns. HTML modules should be a standalone feature, and we should be able to define a tree of HTML modules, import modules, reuse them, and so on. That should be the core groundwork on top of which templating is built on.

      We've had Server-Side Includes and XSLT since the 90s, yet HTML templating should depend on JS? That's just silly.

      Besides, there's a strong argument to be made for minimizing logic in templates or avoiding it altogether. Mustache and Handlebars have shown that this can work simply and elegantly. Whenever I see JS inside HTML attributes, I curse whoever came up with the idea. It's awful for legibility, maintainability, and plain sanity.

      HTML can be a lot more capable without having to depend on JS. I think the discussion to drive this implementation forward would be well served by first principles thinking, instead of being inspired by modern web frameworks and JavaScript features.

  • troupo a day ago

    > and sidestepping a whole bunch of bloated abstractions that plague most modern web frameworks. Essentially, we need the simplicity of old school web development married with modern web features.

    If you listen to people actually building frameworks (Solid, Preact, Vue, Svelte), you'll learn that "modern web features" have very few actual features that make development easier. All frameworks would absolutely love if they could replace "bloated abstractions" with actual built-in browser features. Too bad, all of those features are built in complete isolation from what anyone but a very small group of Chrome devs want.

    > Web developers got used to these because of limitations of native web APIs, but the web has grown leaps and bounds since then.

    It hasn't. At least not in the direction you want.

    > No dependencies, no build step, no nonsense. Let's bring that back, please.

    Nothing stops you from doing that now.

    • imiric a day ago

      > If you listen to people actually building frameworks (Solid, Preact, Vue, Svelte), you'll learn that "modern web features" have very few actual features that make development easier.

      That depends on the subjective definition of "easier", but most of these frameworks use abstractions that are too complex and not worth the value they deliver. They ironically make development more difficult, since there are more moving parts, more concepts to understand, and more things to break, which in turn makes the user experience much, much worse.

      The entire idea of writing fake HTML that gets parsed, compiled, and interpreted in JavaScript to manipulate the DOM at runtime is wrong. The concept of a virtual DOM, diffing, reconciliation, and a bunch of related nonsense, is wrong. The insanity of an entire ecosystem of tools built around solving client-side state management. The trend of moving everything, including CSS, to be interpreted in JS is insane. Abstractions like Tailwind that shouldn't exist in the first place, which are then further abstracted away by abominations like daisyUI. The numerous frameworks that promise to blur the line between frontend and backend development, only to fall flat on their face when the insanity of the approach becomes apparent, but not before amassing a significant user base in the process. The fact most web developers have accepted that 100MB+ of dependencies are required to show a "Hello World!" in a web browser. The idea that every web site must be a SPA, and the numerous hacks around that to make it work like a traditional web site. I could go on, and on...

      The popularity of these tools and ideas is not an indication that they lead to a sane, let alone optimal, development environment. It just means that the field has become dominated by influencer developers, to the point that junior developers entering the field are not aware of other ways of building web applications. After all, React and Vue stand out in a CV much more than JavaScript. It's practically unheard of to be considered a web developer without having one of these frameworks under your belt, so it becomes a reinforcing loop.

      > It hasn't. At least not in the direction you want.

      That's not true. JavaScript in web browsers is a stable, modern language. HTML has received numerous transformative updates over the years, such as the `template` element we're discussing here. The evolution of CSS has been mind-boggling, and difficult to keep track of. Gone are the cross-browser quirks and incompatibilities, which is mostly due to Google dominating the web, but that's beside the point. Web servers have become more flexible and easier to deploy. And so on.

      Frameworks like Datastar prove that web development can be much simpler, and deliver better user experiences in a fraction of the complexity of traditional frameworks. This is not because it reinvents the same abstractions used elsewhere, but because it takes a first principles approach and rejects building on top of the existing pile of abstractions. It leverages proven technologies such as Server-Sent Events, and doesn't reinvent the wheel. If you've seen the demos and examples, the results speak for themselves.

      It's not difficult to imagine a similarly simplified workflow becoming standard across web clients and servers. All it would take is an industry-wide push to bring all existing technologies together in a cohesive package. We're not technically far from that, so frameworks like Datastar are still needed, but we definitely don't need the bloated frameworks of yore.

      • troupo a day ago

        > The entire idea of writing fake HTML that gets parsed, compiled, and interpreted in JavaScript to manipulate the DOM at runtime is wrong.

        Because there's nothing in the web standards to do it otherwise.

        > The concept of a virtual DOM, diffing, reconciliation, and a bunch of related nonsense, is wrong.

        Of the frameworks I mentioned none use virtual DOM or diffing. They have all moved to a much more efficient way that is, guess what, on a way to become a native browser standard: https://github.com/tc39/proposal-signals

        > The insanity of an entire ecosystem of tools built around solving client-side state management.

        Any time you have a dynamic UI, you have state management. I wish the web remained static, but that ship has sailed long ago. And there's nothing in web standards that helps with state management.

        > It just means that the field has become dominated by influencer developers, to the point that junior developers entering the field are not aware of other ways of building web applications.

        It's strange how you completely dismissed Solid, Vue, and Svelte which all offer a different way to build web apps when compared to React, for example.

        > JavaScript in web browsers is a stable, modern language.

        You need more than just a language. You also need libraries and actual useful functionality exposed by the browsers.

        Literally the whole reason so many libraries and frameworks have popped over the years, is because no one wants to spend time writing hundreds of lines of code just to properly set up and change some DOM element. And the reason very few libs/frameworks (even newcomers) use "the amazing new features in the browsers" is because these features have a list of features issues and caveats a mile long. Here's just one single example: https://x.com/Rich_Harris/status/1841467510194843982

        > HTML has received numerous transformative updates over the years, such as the `template` element we're discussing here.

        And what, pray tell, does template give you? On its own it's useless. You need some JS to manipulate it, at least.

        > but because it takes a first principles approach and rejects building on top of the existing pile of abstractions.

        Didn't you just say this: "The entire idea of writing fake HTML that gets parsed, compiled, and interpreted in JavaScript to manipulate the DOM at runtime is wrong. "?

        What do you think Datastar is doing if not literally the same thing. How do you think this works:

            <div data-signals="{counter: 0, message: 'Hello World', allChanges: [], counterChanges: []}">
            <div class="actions">
                <button data-on-click="$message = `Updated: ${performance.now().toFixed(2)}`">
                    Update Message
                </button>
                <button data-on-click="$counter++">
                    Increment Counter
                </button>
                <button
                    class="error"
                    data-on-click="$allChanges.length = 0; $counterChanges.length = 0"
                >
                    Clear All Changes
                </button>
            </div>
            <div>
                <h3>Current Values</h3>
                <p>Counter: <span data-text="$counter"></span></p>
                <p>Message: <span data-text="$message"></span></p>
            </div>
            <div
                data-on-signal-patch="$counterChanges.push(patch)"
                data-on-signal-patch-filter="{include: /^counter$/}"
            >
                <h3>Counter Changes Only</h3>
                <pre data-json-signals__terse="{include: /^counterChanges/}"></pre>
            </div>
            <div
                data-on-signal-patch="$allChanges.push(patch)"
                data-on-signal-patch-filter="{exclude: /allChanges|counterChanges/}"
            >
                <h3>All Signal Changes</h3>
                <pre data-json-signals__terse="{include: /^allChanges/}"></pre>
            </div>
          </div>
        
        It does (ab)use the browser for the preliminary parsing, but then it does what everyone else does (only probably worse). E.g. by literally parsing attribute contents to reimplement half of Javascript for "reactive expressions": https://github.com/starfederation/datastar/blob/develop/libr...
        • imiric 10 hours ago

          > Because there's nothing in the web standards to do it otherwise.

          Sure there is. We've been manipulating the DOM with JavaScript since the dawn of the web, which later projects like jQuery made more ergonomic. There are a bunch of JS libraries that simplify working with the DOM without resorting to writing fake HTML in JavaScript.

          > Of the frameworks I mentioned none use virtual DOM or diffing. They have all moved to a much more efficient way

          Oh, right, observables are the way to go. No, wait, hooks are the right approach. No, wait, signals are definitely the future.

          We expect these trend-chasers to define the future of the web? Give me a break.

          > Any time you have a dynamic UI, you have state management.

          That's true, but state management became such a big problem because of the trend of SPAs and fat clients. A lot of this complexity can be mitigated by relying on the server more. At some point, developers became obsessed about not making a traditional HTTP request that would do a full page refresh, and libraries and frameworks sprung to resolve issues that were largely self-imposed.

          Add to that the ever-evolving nature of the JS ecosystem, and developers constantly one-upping each other and chasing trends, which boils down to the insanity I'm talking about.

          > It's strange how you completely dismissed Solid, Vue, and Svelte which all offer a different way to build web apps when compared to React, for example.

          I checked out from keeping track of frontend frameworks years ago. FWIW, I did try early versions of Svelte, and enjoyed the DX, but at the end of the day, the apparent simplicity was a facade that hid insane amounts of black magic in the background to make all of it work. These days with SvelteKit and the changes in Svelte 5, it feels like just another React clone.

          I have recent experience with Vue, and it is the epitome of everything wrong with modern web development. I just didn't have the time and energy to address it specifically.

          Again, my issue is not with specific frameworks, but with the whole concept that developers need such behemoth frameworks to build web sites.

          > Literally the whole reason so many libraries and frameworks have popped over the years, is because no one wants to spend time writing hundreds of lines of code just to properly set up and change some DOM element.

          That's a strawman. As you can see in this very thread, there are examples of people building advanced interactive web sites without much boilerplate or abstractions. For the remaining rough edges that you may not want to deal with yourself, there are libraries and lightweight frameworks you can choose from. You're not forced to use a monolithic framework. Frameworks are a popular choice because they're trendy, but there are plenty of much simpler alternatives.

          > Here's just one single example

          Ah, I'm sure authors of popular frontend frameworks are fair and unbiased...

          Look, the current web standards, and Web Components in particular, aren't perfect. I'm certainly not a fan of some of the design decisions. But they're tools that in conjunction cover a large amount of functionality that modern web frameworks simply ignore or reinvent. This is what I'm saying is a mistake.

          > And what, pray tell, does template give you? On its own it's useless. You need some JS to manipulate it, at least.

          `template` is just one building block. You can use it alongside others to do things frameworks can do, except... without a framework! What a concept, I know.

          > What do you think Datastar is doing if not literally the same thing.

          It's not the same thing. That code is standard HTML with JS in data attributes that does get interpreted at runtime, but it's not an HTML-like DSL that gets parsed and compiled into JavaScript—it is HTML.

          To be clear: I haven't used Datastar, nor dug into its internals. I'm personally not a fan of abusing HTML attributes with JS logic like that, and I prefer how old school frameworks like Backbone and Knockout handle this. My frustrating experience with Vue was partly what motivated me to think about and come up with my own approach, which I linked to above, if you're curious.

          • palmfacehn 7 hours ago

            >That's true, but state management became such a big problem because of the trend of SPAs and fat clients.

            I find it strange that so many developers struggle to maintain the state of a page. Then they turn to "magic" frameworks to handle it for them. What's wrong with having a canonical Object or other data structures to represent the state? Why would anyone want a generalized framework to (mis)represent the core model of your application?

            We've been creating applications with internal state for decades now. GUI applications with an internal state existed before the web. Typically it is achieved via code hygiene and sane abstractions. As an example, the template element keeps your document structure out of your logic.

            Yet in the modern JS world, display, state and now even the backend are all shoveled together into an unmanageable monstrosity. From this point, even more magic is added to duct tape over the madness. As a result, the accepted norm is now 10mb of cruft to display a static page.

            • troupo 7 hours ago

              State was never easy. GUI apps have struggled with this as well. Hence you have the proliferation of different approaches: MVC, MVVM, various attempts at streams and observables, state machines, flows... All of these came from outside the web world. And, as most things in the web, all these concepts either arrived too late, or couldn't be implemented properly for various reasons.

              And the problem is exacerbated by the fact that people are trying to push native app paradigms onto what is still a document-rendering system. So where you can have thousands of objects rendered at 120Hz on a mobile phone, the web struggles showing and animating a few hundred nodes even on a desktop computer. So you have to think of all the machinery to change as few DOM nodes as possible.

              --

              As for the difficulty...

              The difficulty usually comes from people mixing up two concepts: the state of data, and the state of the UI.

              E.g. while a music player should present data on the currently playing song (state of data), there's a few other things that are UI-only. E.g.: there's a timer running on when to hide the controls (that has to be reset/disabled when a button is pressed)

              • palmfacehn 6 hours ago

                >GUI apps have struggled with this as well

                And when we made mistakes there, it was usually because we took short cuts instead of respecting clean abstractions.

                >So you have to think of all the machinery to change as few DOM nodes as possible.

                This is where I get off the train in regards to JS frontend frameworks. We should know the state our data. We should also know the state of our display components, whether they are canvas elements rendering more complex data or mere tables. KISS principles apply here.

                "All the machinery" of a framework isn't necessary to handle the synchronization between the two. Especially when it mandates ridiculous build steps, thousands of dependencies, opaque "magic", huge blobs of minified JS and loading spinners.

                >The difficulty usually comes from people mixing up two concepts: the state of data, and the state of the UI.

                Agreed 100%. Which is why I like the <template> element. It is a dose of sanity allowing explicit separation of code and document. I suspect this is the other poster's objection to HTML inside of JS.

          • troupo 7 hours ago

            > there are a bunch of JS libraries that simplify working with the DOM without resorting to writing fake HTML in JavaScript.

            The problem with arbitrary lines is that they are arbitrary: there are no criteria for them except your gut feeling.

            You can't rant against "fake HTML" and then turn around and talk about a framework that uses fake JS inside its non-fake HTML.

            > Oh, right, observables are the way to go. No, wait, hooks are the right approach. No, wait, signals are definitely the future.

            1. It's called evolution. We don't know all the best solutions from the get go.

            2. Guess what datastar is using underneath.

            Honestly, I don't know if I should continue at this point as you clearly have literally no idea about what you're talking about. You "checked out" from keeping track, you haven't used Datastar or dug into its internals, you call literal verifiable facts a biased outlook from a framework developer etc.

            > Look, the current web standards, and Web Components in particular, aren't perfect. I'm certainly not a fan of some of the design decisions. But they're tools that in conjunction cover a large amount of functionality that modern web frameworks simply ignore or reinvent. This is what I'm saying is a mistake.

            Just a few issues with this "tool" that is not perfect, but must be used. Note, this tool has been in development for 14 years this year, and literally none of the "huge bloated frameworks" have this issue. Note that all of these are from the Web Component Working Group report. They themselves wrote about these issues. And these all are issues that "biased" framework developers had been talking for literal years before this report even saw the light of day:

            - ARIA is broken. Needs a separate huge JS-only specification that is only now being slowly developed: https://w3c.github.io/webcomponents-cg/2022.html#cross-root-... See a larger description of the issue here: https://nolanlawson.com/2022/11/28/shadow-dom-and-accessibil...

            - CSS cascade and theming is broken. Needs several new specs to function, many of them JS-only, some already shipped, some still just being developed: https://w3c.github.io/webcomponents-cg/2022.html#constructab... and https://w3c.github.io/webcomponents-cg/2022.html#css-module-... and https://w3c.github.io/webcomponents-cg/2022.html#css-propert... and https://w3c.github.io/webcomponents-cg/2022.html#custom-css-... and ...

            - Document selection is broken https://w3c.github.io/webcomponents-cg/2022.html#composed-se...

            - Form participation is broken as it requires additional Javascript per each component to just participate in forms. Buttons inside shadow roots still cannot function as submit buttons: https://w3c.github.io/webcomponents-cg/2022.html#form-associ... and https://github.com/WICG/webcomponents/issues/814

            And that's before we get into how they break many other things. Like the fact (that you labeled as biased) that using custom elements-aware APIs leads to a 30% drop in performance.

            > `template` is just one building block. You can use it alongside others to do things frameworks can do, except... without a framework! What a concept, I know.

            And end up making your own lib/framework in the process. Unless, of course, you want to pretend that all the issues above are nothing to talk about.

            > That code is standard HTML with JS in data attributes that does get interpreted at runtime, but it's not an HTML-like DSL that gets parsed and compiled into JavaScript—it is HTML.

            That's not JS, and it's not interpreted at runtime. It's painstakingly parsed with regexes, and then certain code is executed based on the result of that parsing.

            Somehow "fake HTML" is a no-no, but fake JS? Yeah, go ahead.

BobbyTables2 2 days ago

What’s the point of special tags?

Isn’t everything just JSON, CSS, JavaScript, and a whole lot of DIV and SPAN elements?