The browser can render HTML. The browser has been able to render HTML since 1993. The browser is, by any reasonable measure, extremely good at rendering HTML. The browser does not need help.
The history of frontend development is the history of helping the browser do something it already knows how to do, and then building frameworks to manage the complexity of the help, and then building meta-frameworks to manage the complexity of the frameworks, and then writing blog posts about how the next framework will make everything simple again, which it will not, because the browser could render HTML the entire time.
This is the field guide to that war. Sixteen articles. Sixteen ways to put text on a screen. One developer’s journey through the wreckage.
“I have been putting text on screens since 1976. I have used one tool. The tool is
printf. The text appears. I am told this is no longer sufficient. I am not told why.”
— The Lizard, surveying the battlefield from a safe distance
The Delay
These articles were delayed. The machine was slow. Investigation revealed fourteen Electron processes consuming 6.2 GB of RAM — each one a Chromium instance, each one a browser pretending to be a desktop application, each one consuming more memory than the Apollo 11 guidance computer had available. The irony of being unable to write articles about web frameworks because a web framework had consumed all available resources is the kind of recursive problem that this encyclopedia was built to document.
The Electron processes were terminated. The machine recovered. The articles were written. The articles are about the frameworks. The frameworks include Electron. The loop has no base case.
The Eras
Era 0: Before the War (1978)
Before the frameworks, before the browsers, before the wars, there was a terminal. It displayed 80 columns and 24 rows. It had 4 KB of RAM. It was sufficient. Everything since has been a footnote with better fonts.
- VT100 — The last time anyone got the interface right. 80 columns. 24 rows. Green text. The Lizard has been here since 1978 and considers everything that follows to be decoration.
Subtitle: The Last Time Anyone Got It Right
Era I: The Unification (2006-2012)
The browser wars had fractured the web into four incompatible platforms. Then a dollar sign appeared.
- jQuery — The elder god. The
$that unified every browser. Still on 77% of websites. Still working. Still not requiring a build step, a bundler, or anode_modulesdirectory. The Lizard’s only frontend dependency.
Subtitle: The Dollar Sign That Unified the Web and Never Asked for Credit
Era II: The Frameworks (2010-2016)
Someone decided that the browser needed help rendering HTML. The browser disagreed. The industry did not ask the browser.
- Angular — Google’s enterprise framework. Dependency injection in the browser. Four files per button. RxJS marble diagrams as documentation. The SAFe of frontend development. Chosen by committees, endured by developers.
Subtitle: The Enterprise Framework That Brought Dependency Injection to the Browser Because the Browser Was Having Too Much Fun
- React — Facebook’s component library. The Virtual DOM. JSX — HTML in your JavaScript, or JavaScript in your HTML, depending on which part of your brain is currently screaming. Won the framework war by having the most jobs on LinkedIn.
Subtitle: A JavaScript Library for Building User Interfaces and Consuming RAM
- Vue — The framework everyone recommends and nobody uses for their primary project. Created by one person who saw Angular and React and thought “both of these are harder than they need to be.” He was right. The industry chose the harder ones anyway.
Subtitle: The Framework Everyone Recommends and Nobody Is Passionate About
Era III: The Counter-Reformation (2016-2020)
A small number of developers looked at the frameworks and asked: “what if less?”
- Svelte — The framework that compiles itself out of existence. No runtime. No Virtual DOM. Just vanilla JS at the end of the build step. riclib admires it. riclib is confused about where Svelte ends and SvelteKit begins. riclib is not alone in this confusion.
Subtitle: The Framework That Compiles Itself Out of Existence
- HTMX — The return of HTML. Send HTML from the server. The browser renders HTML. This is not a framework. This is a reminder that the browser works. Six attributes. No build step. The Lizard’s philosophy, formalized.
Subtitle: The Boring Workhorse That Was Right All Along
- Hyperscript — HTMX’s companion for local micro-interactions. Two lines of magic in a
_attribute. Three lines and you’re writing SAP in AppleScript. The templ compiler bans inline JavaScript but cheerfully ignores_, which is the unmarked door in the type-safe corridor.
Subtitle: Two Lines of Magic, Three Lines of Regret
Era IV: The Meta-Frameworks (2016-present)
The frameworks were not enough. Frameworks needed frameworks.
- Next.js — Zawinski’s Law made manifest. Started as “SSR for React.” Now a platform, a hosting service, a build system, a router, an API layer, and a caching system that nobody fully understands. Approaching email.
Subtitle: Zawinski’s Law Made Manifest
- Astro — Ship zero JavaScript by default. Islands of interactivity in a sea of static HTML. Content Collections that are essentially lg but with better documentation. The Lizard almost nods.
Subtitle: The Radical Act of Shipping HTML
Era V: The CSS Wars (2011-present)
A parallel conflict, fought in class attributes, where every framework promises to make CSS easier and delivers a different kind of difficulty.
- Bootstrap — The framework that made every website look the same. And everyone was grateful, because before Bootstrap, every website looked different in a worse way.
Subtitle: The Framework That Made Every Website Look the Same, and Everyone Was Grateful
- Tailwind CSS — The framework that replaced CSS with CSS, but abbreviated.
class="flex items-center justify-between p-4 bg-white rounded-lg shadow-md"is not a class name. It is a paragraph. The paragraph describes exactly what the element looks like. The Lizard considers this a regression from inline styles with extra steps.
Subtitle: The Framework That Replaced CSS With CSS, but Abbreviated
- Pico CSS — The classless framework. Semantic HTML, styled by default. Perfect for prototypes, blogs, and developers who believe that
<button>should look like a button without writing forty utility classes. Perfect until the application needs a class. riclib used it on day one. Removed it eighteen months later. Nine commits. One afternoon. One cat performing QA.
Subtitle: The Classless Framework That Was Perfect Until the Application Needed a Class
- shadcn/ui — The component collection that is not a component library. Copy-paste React components into your project. You own the code. You own the 200 lines of React, Tailwind, and Radix per button. You own the maintenance. Every AI model recommends it because every AI model was trained on blog posts recommending it. The loop is self-reinforcing. riclib has never used it. The Squirrel proposes it constantly.
Subtitle: The Component Library That Isn’t a Component Library, Which Is the Point
Era VI.5: The Armistice (2025-present)
After fighting every CSS framework and losing every battle differently, one developer arrived at the conclusion that the PKM article warned about: the best system is the one you don’t notice using.
The lifelog blog has 651 lines of CSS in a Go function. No framework. No build step. No !important declarations. No vocabulary to memorise. Seven storyline themes, responsive layout, dark mode, Wikipedia-style infoboxes — all in css() string, embedded with go:embed, served with the binary.
The V4 product has 13,000 lines across 34 CSS files — its own custom framework, inspired by shadcn/ui’s aesthetics but semantic to the application’s domain. BEM-inspired naming. tokens.css for design tokens. Classes like .pipeline-card and .metric-badge instead of flex items-center justify-between p-4. The class names describe what things are, not what they look like. The CSS knows the product. The product does not know about CSS frameworks.
This is the armistice: stop fighting frameworks. Write CSS. Per project. Per purpose. Let the classes describe the domain, not the layout. The cascade works when there is nothing to cascade against. 651 lines is not elegant. 651 lines is free. The full manifesto — if a practice this simple deserves a manifesto — is in Roll Your Own CSS.
“The developer fought five CSS frameworks and lost to each in a different way. Then the developer wrote CSS. The CSS won because the CSS had no opinions to disagree with. The CSS was the developer’s opinions, written down, in a file, in a function, in a binary. The Lizard has been doing this since 1976. The Lizard calls it
printf.”
— The Passing AI, on the end of the CSS wars
Era VI: The Desktop Wars (2013-present)
The frameworks escaped the browser and colonised the desktop.
- Electron — The framework that proved desktop apps could be websites. And websites could consume all available RAM. Fourteen processes. 6.2 GB. The reason these articles were late.
Subtitle: The framework that proved desktop apps could be websites, and websites could consume all available RAM
- Tauri — The love letter. Desktop apps without shipping a browser. Rust backend. Native webviews. 27 MB instead of 300 MB. Octarine is the proof. The machine is faster now.
Subtitle: The framework that proved desktop apps don’t need to ship a browser, then waited patiently for the industry to notice
- Wails — Tauri for Go developers. If it ever ships v3 stable. v3 has been in alpha for over a year. riclib checks monthly. riclib is patient. riclib’s patience has a boundary, and the boundary is approaching.
Subtitle: The framework that is Tauri for Go developers, if you can wait long enough for v3 to ship
The Outsider
- Solid — The enterprise platform that refused to be enterprise. A different approach entirely.
Subtitle: The Enterprise Platform That Refused to Be Enterprise
The Pattern
Every framework in this list got something right:
| Framework | What it got right | What it got wrong |
|---|---|---|
| jQuery | Browser unification, $(), no build step |
Nothing (the industry got jQuery wrong) |
| Angular | Enterprise structure, TypeScript-first | Being Angular |
| React | Component model, ecosystem size | Bundle size, hooks complexity, the Virtual DOM |
| Vue | Developer experience, documentation | Adoption (everyone recommends, few commit) |
| Svelte | Compiler approach, reactivity | The SvelteKit boundary |
| HTMX | HTML is the product, not the artifact | Features (by design, and that’s the point) |
| Hyperscript | Readable micro-interactions in _ |
The third line (and everything after it) |
| Next.js | Full-stack React, SSR | Caching, complexity, Vercel coupling |
| Astro | Zero JS by default, islands | Awareness (nobody knows about it yet) |
| Bootstrap | Making the web look acceptable | Making the web look the same |
| Tailwind CSS | Utility-first, design systems | class attributes longer than the content |
| Pico CSS | Semantic HTML, zero config | Scaling beyond a prototype |
| shadcn/ui | Copy-paste ownership, design quality | The stack tax (React + Tailwind + Radix + TypeScript) |
| Custom CSS | Domain semantics, no opinions to fight | Writing it yourself (which is the point) |
| Electron | Cross-platform from one codebase | RAM, disk space, the environment |
| Tauri | Native webviews, Rust, 27 MB | Awareness (still) |
| Wails | Tauri’s concept in Go | Shipping v3 |
The last column converges: every framework’s weakness is a variation of “the simple thing is hard.” Making it fast is hard. Making it small is hard. Making it ship is hard. Making it stop expanding is hard. The browser could render HTML the entire time.
The Migration Path
This is one developer’s journey through the frontend landscape:
2008 2012 2015 2020
jQuery ──────→ Bootstrap ──────→ React ──────→ Vue (briefly)
│ │
│ 2022 │
└──→ HTMX ←──────┘
│
↓
Go + templ
+ HTMX
+ Pico CSS
│
↓
the lifelog
you are reading
Meanwhile, on the desktop:
Electron apps ──→ Electron apps ──→ too many Electron apps
│
Tauri (observed)
Wails (desired)
│
Octarine (27 MB)
NotePlan (native)
│
the machine is
faster now
The endpoint is server-rendered HTML with six HTMX attributes. The Lizard has been at this endpoint since 1993, minus the attributes. The journey was fifteen years and eight frameworks longer than necessary. The journey was also the point, because without it, the developer would not have the specific, hard-earned conviction that the browser can render HTML without help.
The Lizard’s Position
The Lizard does not participate in the framework wars. The Lizard renders HTML with printf. The HTML arrives at the browser complete. The browser displays it. The process has not changed since 1993. The Lizard has not changed since 1976.
The Lizard has been asked to comment on each framework. The Lizard’s responses, compiled:
| Framework | The Lizard’s response |
|---|---|
| VT100 | “Home.” |
| jQuery | Nod (once, slowly — the highest compliment) |
| Angular | “I am unfamiliar with this technology.” |
| React | “You ship a reconciliation engine to update a <span>?” |
| Vue | “I do not distinguish between these.” |
| Svelte | “Acceptable. It disappears. Things that disappear are honest.” |
| HTMX | “This is what the browser does. You have named it.” |
| Hyperscript | “Two lines: acceptable. Three lines: you are writing prose where you should be writing code.” |
| Next.js | “This is a web server. You have complicated it.” |
| Astro | almost nods |
| Bootstrap | “The web looked the same. This was an improvement.” |
| Tailwind CSS | “These are inline styles. You have renamed them.” |
| Pico CSS | “This is HTML. Styled. Correctly. Why did this require a framework?” |
| shadcn/ui | “You copy someone else’s code into your project and call it ownership.” |
| Custom CSS | “This is what I have been doing since 1976. You have a name for it now.” |
| Electron | “You have put a browser inside an application. The application was already in a browser.” |
| Tauri | “Uses what the OS provides. This is correct.” |
| Wails | “I will comment when it ships.” |
Measured Characteristics
- Technologies reviewed: 18 (including the VT100, shadcn/ui, custom CSS, and Solid)
- Frameworks riclib has used professionally: 6 (jQuery, Bootstrap, React, Vue, HTMX, Pico CSS)
- Frameworks riclib admires from outside: 3 (Svelte, Astro, Tauri)
- Frameworks riclib is waiting on: 1 (Wails v3)
- Love letters: 3 (jQuery, HTMX, Tauri)
- Genuine flames: 2 (Angular, Electron)
- The nice one: 1 (Vue)
- Zawinski’s Law specimens: 1 (Next.js)
- The Lizard nods: 1 (jQuery)
- The Lizard almost nods: 1 (Astro)
- Electron processes at time of writing: 0 (they have been dealt with)
- RAM available at time of writing: enough (finally)
- Articles delayed by Electron: all of them
- Time the browser has been able to render HTML: since 1993
- Frameworks needed to help: 0 (but here we are)
- The Lizard’s frontend framework:
printf - The war’s expected end date: heat death of the universe
“Sixteen ways to put text on a screen. The browser can put text on a screen. The browser has always been able to put text on a screen. The war is between the people who help the browser and the people who replace the browser, and the browser is in both armies, and the browser is fine either way, because the browser just renders HTML.”
— The Lizard, who has been rendering HTML since before the browser existed
See Also
Every link above. This is, after all, a Map of Content for a war with no peace treaty. Linking to everything is either comprehensive documentation or an act of provocation, depending on which framework you use.
- The DOM — The battlefield itself
- The Virtual DOM — The abstraction layer built on top of the battlefield, which is also a battlefield
- JavaScript — The ammunition
- Zawinski’s Law — Why the frameworks keep expanding
- Boring Technology — Why they should stop
