Skip to content

Introduction: The Operating System Underneath

The next decade of interfaces won’t be hand-authored.

Most of the screens a person looks at today were drawn by someone, in advance, using a framework they chose deliberately. A designer specced it; a developer implemented it; the result shipped to every user the same way. That model has worked for the web’s entire history, and it’s about to stop being the default.

What’s coming is interfaces that are dynamic, personalized, and generated by AI on demand — a UI surface composed for one user, for one task, for the specific device and context in which they happen to be sitting at a given moment. Chat is the obvious early form of this: a pure text interface whose content is generated per conversation. Chat is also transitional. Even chat surfaces themselves are starting to embed richer components: cards, tables, charts, embedded forms, interactive widgets. The pattern won’t stay confined to chat any more than the web stayed confined to documents.

These interfaces have to ship on something. The economics of the situation make the answer clear. Nobody is going to tolerate downloading a two-hundred-kilobyte framework runtime to render a single AI-generated card on a watch face. Nobody is going to ship five different runtime variants for five different device classes. The substrate that’s left — the only one that’s already deployed, capable, and present everywhere from the smallest phones to the largest TVs — is the browser engine. The web’s native APIs. The platform underneath.

This is a book about that platform. How it became one underneath us, while the industry was busy building abstraction layers on top of it. Why those layers can feel like magic until you look at what’s actually doing the work. And how to build software that takes the platform seriously — for today’s products and for the AI-generated interfaces that are coming next.

The frontend stack we use today is a long accumulation, layer by layer, each one solving a real problem of its day.

CSS arrived because mixing presentation into HTML was making sites unmaintainable. JavaScript arrived because pages needed to do something between page loads — and over the next two decades the TC39 standards committee turned that scrappy ten-day prototype into one of the most rigorously specified languages in widespread use, with TypeScript later layering structural typing on top and quietly becoming the default. Plugins like Flash and Silverlight arrived because the browser couldn’t yet deliver rich experiences on its own. Ajax arrived because users were tired of full-page reloads for every interaction. jQuery arrived because the browsers of the late 2000s couldn’t agree on the basics, and the IE6 era made writing portable JavaScript genuinely difficult. Backbone, Prototype, MooTools, and the early structure libraries arrived because the resulting JavaScript code had grown beyond what could be maintained as scattered scripts. npm arrived to make all that code shareable and ended up creating an ecosystem of transitive dependency trees thousands of packages deep — a fertile environment for the kind of supply-chain incidents we’ll come back to: left-pad in 2016, event-stream in 2018, the steady drumbeat since. Angular and Ember tried to bring serious application discipline to the resulting mess. React, in 2013, reframed the whole problem as a function from state to UI — a genuine intellectual breakthrough that quietly remade the industry. Vue arrived as the independent answer that prioritized approachability. Solid and Svelte pushed back on React’s runtime model with fine-grained reactivity and compile-time approaches. Next.js, Remix, and the meta-framework era arrived because single-page applications had ballooned in cost and lost things — routing, server rendering, data loading, deployment discipline — that needed to come back. Underneath all of them, the JavaScript runtimes shifted too: Node became the standard, Deno tried to rework it, Bun won the speed race and was eventually acquired by Anthropic.

None of these were mistakes. Each was a serious answer to a problem that genuinely needed answering. The people who built them — Brendan Eich, John Resig, Jordan Walke and the early React team, Evan You, Ryan Carniato, Tanner Linsley, Ryan Florence and Michael Jackson, Ryan Dahl, Jarred Sumner, and many others we’ll meet by name — are world-class engineers, and the systems they shipped are remarkable feats of design.

The point of revisiting them is to understand the why: what each layer was solving for, what the world looked like when that solution was the right one. That’s the contextual depth the rest of the book is built on. The world has changed underneath all of those layers, and the answers built for one world don’t always fit another.

While the frontend industry was busy building above the platform, the platform itself was changing.

Between 2015 and now, browsers shipped an astonishing amount. Native ES modules, so code can be organized without a bundler. fetch, promises, and async/await, so HTTP doesn’t need a wrapper. Custom elements, shadow DOM, slots, and templates — a real component model, in the platform, with no framework required. Three flavors of observer (mutation, intersection, resize) for reacting to the DOM without polling. The History API and URL APIs, so routing isn’t something the page has to invent. FormData, constraint validation, and ElementInternals, so forms are programmable in a serious way. Native <dialog> and the popover API. CSS custom properties, cascade layers, container queries, :has(), view transitions. Service workers and web workers. A full storage tier from sessionStorage through IndexedDB to the Cache API. BroadcastChannel for cross-tab messaging. AbortController for cancellable async work. Form-associated custom elements, so the components we author can participate in the platform’s existing form model rather than reinventing it.

Most of the defaults that frontend developers still teach were formed when none of this existed.

The frontend stack was largely shaped by a generation of developers solving problems that were real at the time: the IE6 era, the inconsistency of pre-evergreen browsers, the absence of a real component model, the lack of native data primitives, the assumption that the page was the unit and the framework was the application. Many of those problems have quietly disappeared. The wrappers and shims and meta-layers built to work around them are still in our codebases, still in our defaults, still in the answers we give junior developers when they ask how something is done. The platform changed; the habits didn’t.

If we were starting today — knowing what the platform now offers — what would we build?

There’s a particular kind of developer who’s good at answering that question. Not necessarily the most senior, and not necessarily the most up-to-date. The thing they have is contextual depth: a feel for what each layer of the stack was solving for, what it traded away to do that, and what’s still underneath when you peel it back.

That depth used to come from time. You worked through enough eras of the platform to feel its shape — the Mosaic and Netscape years, the rise of Internet Explorer, the IE6 era and what it cost everyone, the move away from Flash, the long Ajax climb, the rise of the SPA, the swing back to server rendering. You watched abstractions arrive and saw what they were solving for. You watched some of them outlive their problems. You came out the other side knowing not just what to do, but why the field organized itself the way it did.

In the AI era, that contextual depth has become something close to a superpower.

AI tools are now genuinely capable of writing frontend code, but they write the frontend they were trained on, which is the frontend of the last decade. They reach for the same patterns, suggest the same dependencies, and wrap things that don’t need wrapping — because that’s what the corpus of code they learned from did. A developer who only knows the surface, who can ask AI to follow the latest Next.js docs but can’t evaluate whether Next.js is the right tool for the situation, gets exactly the kind of code AI is best at producing: more of what already exists. A developer with contextual depth can use the same tool to do something different. They can ask for an implementation, evaluate whether it makes sense, recognize when an abstraction is unnecessary because the platform already provides it, and steer the work toward something simpler, lighter, and more durable.

This book is partly an attempt to transmit that depth. The history is here to give you the relationships between problems and solutions that make modern judgment possible. By the end, you should be able to look at a piece of frontend code and see not just what it does, but what historical problem it was originally written to solve and whether that problem still applies. That’s the lens that makes the platform legible. It’s also the lens that lets you build for what’s coming.

The book moves in three movements.

The first traces how we got here. Each chapter takes one layer of the modern frontend stack and works through what it was solving for, who built it, and what changed once it became default. We move from the document web through CSS, JavaScript, plugins, Ajax, jQuery, the early structure libraries, MVC frameworks, React, the meta-framework era, the JavaScript runtimes underneath, the rise of mobile and the move from responsive to adaptive design, and the quiet inflection where the browser became the de facto native application platform — VSCode, Slack, Discord, Figma, Cursor, the desktop ChatGPT and Claude apps all running on Chromium in trench coats. The figures and stories in this part — Tim Berners-Lee at CERN, Marc Andreessen and Mosaic, the Macromedia and Apple Flash drama, John Resig and jQuery, Jordan Walke and React’s controversial debut, Brad Frost and the design-system industry, Ryan Dahl and the long arc of Node-Deno-Bun — are part of the substance, not decoration. They’re how you build the relationships between problems and solutions that make the rest of the book stick.

The second walks through the modern browser as a platform, not a render target. HTML treated as an application language. CSS treated as a runtime, not styling decoration. The DOM treated as a context tree, not a render artifact. Forms treated as transactions. Accessibility treated as a contract. Custom elements as a component model that doesn’t need a framework to exist. These chapters look like they’re about web standards, but they’re really about architecture; the standards are just where the architecture lives.

The third builds on top of that platform. First by hand — a small runtime, a shell, modules, boundaries, a metadata layer, native components — built piece by piece so the moving parts stay visible. Then in maintained form, a framework called Kitsune that takes the same ideas to production scale. Kitsune doesn’t appear until the final third of the book, and that’s deliberate: by the time it arrives, you’ll already have most of the design in your head, and Kitsune will read as the natural next step rather than a sales pitch.

The book closes by returning to the future-of-UIs argument with the depth to engage with it seriously. What does it actually take to ship dynamic, AI-generated, personalized interfaces that work, anywhere, with the security and reliability that real software demands? The answer is the architecture the book has been building all along, plus a deeper understanding of why the platform underneath is what makes it possible.

This isn’t an anti-framework book. React, Vue, Angular, Solid, Svelte, Lit, Next.js, Remix, Astro, the entire meta-framework ecosystem — all of these are serious engineering, and most of them will continue to be useful for many years to come. The argument here is that we’ve been thinking about them at the wrong altitude. Underneath every one of them is the same operating system: the browser, with its APIs and its native primitives. Treating that operating system as a real platform — rather than something to be papered over — is what changes the kind of software you can build.

It also changes how long that software lasts. The browser commits, by design and by spec, to backward compatibility: a form written in 1999 still works today. The frameworks built on top of the browser don’t make the same commitment, and code written against them tends to need rewriting every few years to keep up with the framework’s own evolution — Angular 1 to 2, class components to hooks, Webpack to Vite, CommonJS to ESM, the steady churn of npm dependencies that get deprecated faster than they can be replaced. Building on the platform is, among other things, an argument about longevity. The code you ship today should still work tomorrow without intervention, and that becomes load-bearing the moment you start shipping interfaces an AI generated for one user one minute ago.

Even if you never use Kitsune, this book should make you a better frontend developer. It should let you look at the layers you already use — React, Apollo Client, GSAP, Next.js, your design system, your build tool — and see them as what they are: incredible feats of engineering built on top of a platform you can also build on directly when you choose to. That choice, and the judgment to know when to make it, is what the rest of the book is here to give you.