Hello BackflipHTML

I wrote my first website in Notepad.

There were no developer ergonomics whatsoever. No syntax highlighting, no linter, no autocomplete, nothing. It was 1996.

Since then I’ve written HTML by concatenating strings in Perl, by tossing a PHP and HTML salad, more string juggling in the browser, followed closely by imperative mutations to the DOM using Prototype.js.

More recently I’ve suffered the pain of Go’s HTML templates, and I’ve even reached for Mustache templates as late as 2022. But most of the time now I just reach for Vue.

Vue is good.

Let me clarify: If you are building a Single Page Application (SPA), or something that requires a ton of complex DOM mutations on the client side, then Vue is good.

Vue gives you the ability to divide the complexity among components which along with CSS scoping lets you keep control over an ever growing project.

It also gives you a solid developer experience. Fire up the dev server and changes you make in your code editor are reflected immediately in your browser. Flow state achieved.

The problem is I reach for Vue for just about everything that is even mildly interactive, and I am paying the price for it.

I reflexively reached for Vue to implement the frontend of Dropserver. I wanted the Dropserver UI to feel snappy and always reflect the latest data. That meant parts of the pages would be updated in response to user input but also in response to events sent from the server. Primo Vue territory.

What I’m seeing now is that there is a lot of unnecessary complexity in the ds-host code. There is the backend code where all the real work happens, and the frontend that has to keep up with whatever the backend is doing.

SPAs are contagious. Every new feature that displays something in the UI results in work on the server side and then more work to get the data synced to the frontend. That means implementing data models (Pinia stores in my case) and routes to serve the data from the backend. Failing to do so means I’d have to ask the user to refresh the page for changes to show. Oof.

So I’m piling up Pinia stores that duplicate backend data, and the routes that serve this data for everything including the most rarely changed bit of data (user’s email) because that’s what happens when you build a server app and then build an entirely separate browser app to display the first app’s data.

I’ll spare you further whining. Also I want to make clear: Vue is great, I like it. It’s just not the optimal way of building a website or even a typical interactive web application. I haven’t even touched on accessibility and performance issues.

What I Want

The above historical drama is just to say I’ve had time to think about my ideal HTML and web authoring system. So here goes:

Backend First

By default HTML should be rendered on the server. That’s the starting point. That’s the natural place. Default to multi-page apps rendered on the backend and enhance to make them alive if needed. For most cases, that will be good enough, and far less complicated.

Any Backend

I have projects written in PHP (old stuff, but still kicking), Go, and JS. You might have projects in Python and Rust. I don’t want to use a different template system for each of those. So when I say backend I mean all backends. That is the glory of Mustache, it runs everywhere.

And no I won’t to run Node alongside my PHP or Go projects just to SSR.

Streaming HTML

I’m intrigued by the possibilities of streaming HTML. I think it opens doors for making web pages feel fast: stream the “app frame” and then continue with the rest when the data is loaded. But this requires a template runner that can send chunks out before all the data is present.

Preview / Development Server

Working on these backend-first templates should not be a pain. No manual “save-compile-reload” cycles please. There should be a development server that can serve the HTML and refresh automatically on file change.

Developer Tooling

When I write Go my IDE gives me so much helpful information about anything I see in my code. I can right-click and go to definition, type definition, see all references, implementations, etc… It’s all there and instantly available. When I write in Go I get the feeling the system is solid and nothing is left to chance.

When I write HTML and CSS inside of imperative languages it’s much more of a guessing game. Will this CSS selector apply here? What other elements match?

I want authoring of HTML and CSS to be as solid as Go. In fact I want everything in HTML to be legible at the authoring site. Web developers have access to great developer tools in the browser, but in the IDE? Nada.

I should be able to hover on anything and it tells me all the ways it’s connected to the rest of the code. If there is a typo when referencing another template, or a class, I should get a red squiggle underline.

Embrace Web Components

For the frontend interactivity, I want to embrace Web Components. If at all possible, I want my templates to serve as the single source of truth for the component in all its states. I do not want to write HTML or CSS inside of JS strings.

Longevity

In the midst of all this, I also do not want to be continually forced to go through major-revision migrations for this or that dependency. The system that builds these templates should keep a minimal set of dependencies, and these should be as stable as possible.

The Options

There are multiple attempts to make Vue and React work as part of a server-side framework (Next.js, Nuxt.js, Astro.js, Remix, etc…) which theoretically brings some of the advantages that I long for. Unfortunately they are even more of a framework than their frontend-only counterparts. They rope your entire backend into being part of the framework. That’s not what I want. Part of moving to Web Components is to embrace libraries over frameworks as much as possible.

Also, upgrade treadmill anyone? Astro seems to ship major versions more often than I update my site (Dropserver.org is built on Astro.)

Go has something called templ, which brings part of the developer experience of frontend frameworks to pure Go templates. It seems like a solid project. But being Go-only, I’d be looking for something else for my other projects.

I imagine other programming environments have at least a partial solution to this. But that’s part of the problem: each has its own paradigms and none of the tooling can be reused. This dilutes the dev effort across many projects.

BackflipHTML

I never found anything that comes close to my vision of things, and frankly it’s sufficiently off-the-wall that I am not surprised. It became clear a while ago I was going to have to build this myself.

I started thinking about this in 2023, and writing some experimental code in 2024. By 2025 I had settled on a template style (Vue-ish), and libraries needed to make it work. I had a barely functioning prototype. But the vast amounts of work needed to make this a reality held me back.

Then Claude Opus 4.5 came, and with its promise of not being completely awful and my desire to experiment with coding agents I got to work building out more of Backflip.

Current Status

The repo is here (for now, I am eyeing a migration away from Github).

⚠️💀⚡ It’s a hot mess! 💣💥👺

I started with Deno then realized a lot of stuff has to work under Node, so it’s a mix of both. Look, I consider it highly experimental code. I should probably not even share the repo at this point. But it does work to prove that some of this is feasible:

  • It can generate PHP or JS from template code. I’ll add Go later.
  • The language-specific parts are small so implementing a new language should be fine.
  • There is a preview server. I used it the other day for a project and I got in the flow alright.
  • There is a language server and a VSCode extension. Errors show as red squiggles and I can right-click on a CSS selector and see what elements match in the templates, even if the selector spans multiple templates (legacy CSS selectors only for now, modern stuff not yet supported). And vice-versa.
  • Bonus: the preview server does not need the backend to be running. It just invents data to match your template so it can show you a fully rendered template.
  • This preview server also runs in the VSCode extension. You can right-click in the preview in VSCode to go straight to the line of template code that defines the element under the cursor. Neat.
  • The compiler and language generator depend solely on parse5 and acornJS. These are rock solid dependencies that are not on the upgrade treadmill.

What Next

Right now I’m working on web components, and how Backflip templates can help render them on the backend and re-render them on the frontend. It’s a bit of a challenge.

I don’t know how far I’ll take this project. I really want it to exist, but even with Claude’s help it’s a ton of work. Also, I don’t know for sure it will be as great as I imagine it. Maybe there will be too many limitations? Who knows?

I do plan on sharing the development saga publicly. 🍿

Aerospace Engineer turned sofware developer and bootstrappin' entrepreneur.