Skip to main content

…but some of us were watching

First published · Knut Melvær ·

A response to The Descent, the generated frontend history that entered my feed recently. It skipped the CMS decade, Flash, and everyone who was in wp-admin in 2008 (like I was).

Contents

The blog post "The Descent What Happened to the Frontend While You Weren't Watching" has swung past in various feeds lately. Many of my fellow web developers seem to relate to it, probably because we feel some nostalgia for what now feels like simpler times (spoiler: they weren't).

The post opens with this statement:

In 2008 you saved a file called index.html, dragged it onto an FTP client, and watched a little progress bar crawl to the right. When it finished, your website existed.

Well. In 2008, I had left this practice behind and was customizing WordPress templates for my clients, and I was far from the only one. It let us ship websites where the people we built them for could publish content without anyone dragging a file into a remote folder. Yes, I used FTP to upload the CMS files, but also stuff like phpMyAdmin to manage the MySQL database that made the whole thing work.

As someone who wrote an index.html and put it on the web with WS_FTP in 1998, it feels like the piece leaves so much of the story out of the picture.

Like FrontPage and Dreamweaver as tooling? How Flash was the means of giving folks app-like experiences on the web, and how the iPhone killed it? What platforms like LiveJournal, MySpace, and Neopets did in terms of empowering folks to use CSS and HTML to customize their corner of the web without having to know about FTP at all? All the community work that went into making semantic HTML happen?

The historical lacunas aside, which might be forgivable given the focus on "tooling," not zooming out is also why the post ends up too simplistic in its thesis that "every tool is scar tissue over a real wound," and that "somebody hit a genuine problem, built a fix, and the fix created the next problem, which got its own fix" is (the only) reason we're here.

My goal in this post is not to provide the complete and canonical history of web development and frontend tooling. Nor to claim that I have the perfect synthesis of why we are where we are. But by skimming through what went unmentioned in "The Descent," I think I can give enough proof that we have the tooling we have not just because "new tooling creates new problems solved by new tooling, rinse and repeat," but because of the evolution of the web platform itself (specifications, browser capabilities, devices), culture and conversations (conferences, industry blogs, forums), socio-economic drivers (scaling engineering orgs, what gets invested in), and mental models within engineering practice (DRY, KISS, avoiding technical debt).

In my experience, “the pendulum” is more like a flat circle, and we have been everywhere on it, all at once.

Side note: who am I even arguing with?

Before I dive into the depths of history so we can ascend back to enlightenment, it should be said, as I'm typing this post out with my feeble digits like it's 2023, that the blog post reads like it was generated by Claude. The site's own footer confirms it had a hand in it: "Made by David Poblador i Garcia (and Claude, too)." It's an impressive output, probably shaped through a lot of back and forth, and to be fair, a decent descent. But it does leave me wondering if I’m just arguing with someone's output that they kinda didn’t think that deeply about?

Well, it has been read enough and created conversation, so maybe it doesn't matter much where the authorship and thinking start and stop.

I genuinely[1] don't know how to feel about it though. Nor am I on a moral high horse here, I too, am guilty of using Claude to write and being more hands off than I probably should’ve.

The pre-2006 web dev

You can certainly peel the historical layers of frontend and web development back beyond the web itself, to ARPANET, SGML, Usenet, and whatnot, but for the sake of simplicity, let's wake up in the early 2000s. The grown-ups of the early web already scarred by the dot com bubble.

Yes, static authoring of HTML and CSS files, or dynamic generation with PHP and Perl, are things people do. But they're also building websites with FrontPage and Dreamweaver as their frontend tooling. The desktop software gives them UI affordances for handling templates and content at scale (a Dreamweaver template even had locked regions and editable regions, which is a schema if you squint). We're also using framesets, iframes, and Macromedia Flash™ to provide the "fetch new content without reloading the whole page" experience we associate with Single Page Applications today.

Late 90s/early 2000s was also the era of blogging platforms. Many of us were also typing CSS and HTML into text boxes in a browser to customize our LiveJournals, Neopets, MySpaces, and similar personal website builders offered through the web.

Raise your hand if you ever lost a bunch of work because you forgot to keep a copy of your markup elsewhere before you saved it.

The expectations for what you could experience on the web, and what it entailed to develop for it, were starting to set. We started to feel the pain of browsers diverging in what they could render. And we for some reason found it reasonable to impose additional software like Java applets, Flash, RealPlayer, and Shockwave on our users to let them engage with our content. Well, we might have learned something on the way. Right?

We were working within a young platform full of gaps, and routing around them with whatever the culture put in front of us.

Frameworks before there was "frameworks"

At four meters down, David places "The Itch," talks about jQuery, and gives a nod to Backbone.js. But the year before jQuery, in 2005, another David, namely David Heinemeier Hansson aka DHH, gave the infamous 15-minute demo of building a fully functioning blog engine with Ruby on Rails:

Rails handed a generation of web developers the mental model of what a "framework" even is (convention over configuration, MVC, scaffolding), a model the JavaScript world would spend the next decade importing. It has a huuuge impact on the industry (web 2.0 anyone?), and made fullstack development attainable for devs who had regarded themselves as “only frontend.”

And we can’t go without mentioning how CSS Zen Garden (Dave Shea, 2003) was the place to direct people to convince them that separating structure from presentation was the way to go. One HTML file wore hundreds of designs, and the content held still while everything around it changed. You know, the thing you can do with Tailwind Themes (hirr hirr).

These mental models needed rooms to spread in, and 2009 gave JavaScript its own. JSConf (oh how we miss thee) turned a language community into a traveling culture, and at JSConf EU in Berlin that November, Ryan Dahl introduced Node.js, the runtime the entire npm universe in The Descent's lower layers now sits on. It was on stage and in the hallway tracks frameworks won the hearts and minds, before they won the benchmarks.

Web 2.0 and CSS patterns maturing

Between 2006 and 2010 we saw practices around CSS mature as folks needed it to scale within organizations and bigger engineering teams. Jeffrey Zeldman and the community around A List Apart advocated heavily for semantic HTML and separation of concerns. Despite the drama between purist XHTML and the vendor-driven HTML5 that came out of the WHATWG (three browser vendors walking out of the W3C in 2004), practice converged on keeping semantic ties between HTML and CSS. It went deep enough that when Ian Hickson mined about a billion pages of Google's index to decide which new elements HTML5 should get, the community's most-used class names (header, nav, footer) became the tags. Years of conversation, written into the spec itself.

So much dark magic went into making this pattern work at times.

Not a "framework" per se, but a lot of us adopted the Holy Grail pattern by copy-pasting from Matthew Levine's 2006 article on A List Apart:

css
#left {
  width: 200px;          /* LC width */
  right: 200px;          /* LC width */
  margin-left: -100%;
}
#right {
  width: 150px;          /* RC width */
  margin-right: -150px;  /* RC width */
}
/*** IE6 Fix ***/
* html #left {
  left: 150px;           /* RC width */
}

Note the /*** IE6 Fix ***/ at the bottom. The Descent remembers the 2008 file as having zero dependencies and working in every browser, forever. Hah! That is not what I remember.

Anyone who shipped through IE6 remembers that year as conditional comments, CSS reset files, and PNG transparency hacks, all because the browser that won the war in 2001 then stood still for five years. Heck, I even remember when we had the “best viewed in 600x400” on the splash screen we placed before you entered the website (remember splash screens on the web?). That stagnation was a market outcome, and a whole compatibility-shim industry (jQuery included) grew out of it. It took forever for folks to install new browsers.

And speaking of new browsers. We got Google and the elusive page rank algo, keyword stuffing and SEO, and later lighthouse scores. And all the expectations from clients and peers. And later Chrome, that finally introduced the self-updating browser pattern. And with it a pretty fast engine for running JavaScript called V8.

In 2007 the iPhone launched, kicking off the era when frontend developers were forced to think seriously about breakpoints, responsive design, and touch interfaces. The same years gave us Twitter, its many failwhales, and a swath of new web experiences built around user-generated content. In 2010, Steve Jobs killed Flash, which put even more pressure on standards bodies and browser vendors to make HTML/CSS/JS capable of driving richer, more interactive experiences. Ethan Marcotte published "Responsive Web Design" one month later. An extinction event and the radiation that filled the niche, one month apart. And in 2011, Twitter's internal toolkit escaped into the world as Bootstrap, with Foundation from ZURB right behind it, and suddenly every admin panel and side project shipped with the same buttons. And content-driven websites too.

CSS also got its build step years before JavaScript forced one on everyone. Sass (2006) and Less (2009) had us compiling stylesheets long before anyone bundled a module, and Rails made preprocessing a default with its asset pipeline in 2011. When stylesheets had to survive contact with big teams, we reached for methodologies like BEM, naming conventions that worked as social contracts, because at scale the hard problem of CSS was coordinating people. And BEM is a tidy specimen of how these things spread, an internal Yandex convention that became gospel in the West by way of Harry Roberts' "MindBEMding" post and utility-ish-class frameworks like his InuitCSS.

Even today's utility-class orthodoxy did a lap here first. Thierry Koblentz made the case for atomic classes in "Challenging CSS Best Practices" (Smashing Mag was also huge in popularizing certain frontend practices, CSS-tricks too) in 2013 and was treated as a heretic against separation of concerns, the very approach the Zen Garden had sanctified. A decade later the same idea, wearing Tailwind's clothes, became the new dogma. The Descent notes that Tailwind looks like the inline styles you were taught to avoid, and skips the part where we already had that exact fight.

And then there were CMSs!

Now, I might be overly sensitive to this, given my eight years and counting at Sanity (a headless CMS turned Content Operating System), but I find it interesting that the piece doesn't touch CMSs at all. Maybe they're not traditionally thought of as "frontend tooling," but they drove a lot of the conversation and practice around it. The wound they treated is older than any JavaScript itch. Someone who isn't a developer needs to change the page, without calling you.

And it was never a niche. By 2008, WordPress was five years old, WordCamps had been running for two, and for a huge share of working web developers, "frontend development" meant theme hierarchies, The Loop, and whatever TinyMCE decided your editor's markup should be. I can't point to the moment WordPress became the default for me and my peers. It took over the web, famously over 40% of it.

Think of the impact ThemeForest had on frontend development. It launched in August 2008, the same year The Descent has "you" watching an FTP progress bar, and its first listing was a WordPress theme. It made it possible for single devs to earn serious money on their craft, while also making them somewhat responsible for how well those themes actually worked. Or think of the whole bag of hurt that was (is) WordPress plugins, making it possible to inject HTML and CSS into environments you don't control (whose !important wins?).

Even the piece's 2026 field kit repeats the omission. Its recommended stack for a "content site" is a framework, a CSS library, and somewhere to deploy. The content itself is left as an exercise for the reader. (just use sanity, obviously)

Server(less) hosting and git-driven deployment

For a post that starts with FTP as the means of deployment and arrives at "we're back to servers again," I find it interesting that it doesn't talk about how web developers started using deployment tooling like Capistrano and Roots' Bedrock, or approachable services like Beanstalk and DeployHQ that let you keep (S)FTP as the last deployment step while git became the source of truth.

It also doesn't mention the immense influence the Twelve-Factor App manifesto had, or how Heroku popularized continuous deployment and stateless server environments. As frontend developers, we started to be expected to check our work into git and push it to GitHub or GitLab. We also got approachable hosting for more traditional servers, like DigitalOcean.

In 2012, Phil Hawksworth stood on stage at the Fronteers conference and explained that he could "smell your CMS." The WYSIWYG editors of the era leaked HTML soup (not the good kind) into the markup, and sometimes, he argued, a static site generator like Jekyll with your content in plain Markdown files gets the job done better.

Some years later, this pattern got re-popularized through Netlify's clever developer marketing vehicle, aka Jamstack (where Phil also ended up working), and through frameworks like Gatsby, Next.js, and Nuxt, which The Descent does mention, while failing to mention that "the build step" was now happening in git-triggered, server-side deployment pipelines that put the built files on CDNs.

The content had to come from somewhere, though. Markdown in the repo worked fine until the editors showed up, and the missing admin interface came back as a service. Contentful was early out and turned the CMS into an API you subscribe to, with Prismic, Strapi, and a Norwegian one I'd end up working for close behind. Here headless CMSes, the Jamstack, and the new API-driven frameworks converged on one architecture, with content behind an API, code in git, HTML on a CDN, and an editor hitting Publish triggering a rebuild the same way a git push did. Gatsby built a whole framework around sourcing those APIs at build time; Next.js met the same world from the server side.

Developers weren't the only ones leaving the monolith, either. Squarespace, Wix, and Webflow are the spiritual descendants of GeoCities, LiveJournal, and MySpace, hosted homes for everyone the platform web first taught to want one. Every one of them still ships the old escape hatch, a box where you paste raw HTML and CSS, and the text box from that MySpace-era screenshot earlier in the post lives on as a paid feature called custom code. The monolith got squeezed from both ends as developers pulled the content out through APIs and everyone else handed the whole stack to a SaaS.

(Interestingly, at Sanity we now see a lot of movement from Webflow into Sanity/Astro/Next.js stacks because of agents lowering the threshold to web development and UI-driven interfaces becoming bottlenecks).

And that's the part "we're back to servers again" skips. The server we came back to renders from an API, while the database, the editing interface, and the content itself all live somewhere else now. The content seceded from the monolith somewhere around here, and it never moved back in. Same HTML on the surface, a different architecture underneath. From directly above, a spiral looks exactly like a circle.

So, full circle?

Getting to the bottom of The Descent, it concludes that we've come full circle and have servers and relatively simple syntax again. I'm not sure whether we dug down through our own basement and hit the front porch, or ascended through the seven heavens to find the ogdoadic state of web development waiting for us (I mean, Astro has a certain celestial vibe to it?).

The frontier of 2026, the stuff the sharpest people are most excited about, is render the HTML on the server, ship almost no JavaScript, and use the web platform instead of fighting it. Astro, islands, server components, htmx, "the pendulum is swinging back," all of it points one way: toward a fast page made mostly of HTML, served from a CDN.

I must say, the sharpest people in web development were always excited about shipping almost no JavaScript and using the web platform, I have heard this refrain for at least two and half decade. That's a static stance in our profession. There will always be folks who gets super stoked about reducing complexity to a simple plain text file with markdown in it. Just look at the new agent frameworks like Vercel’s eve that is all like “make an agent with some markdown in a folder.”

But if you peel off that layer of abstraction, making agents for production involves a lot of concepts that goes far beyond problems in frontend development, but you are now expected to tackle as a developer who got into this because you wanted to make websites.

How progressive disclosure looks like for building agents

And on that note, “even” the folks behind Next.js would argue you should avoid shipping a bunch of unnecessary JavaScript; they just weigh the trade-offs differently. Is it OK to load more JavaScript up front if it makes subsequent browsing feel instant? If your team is comfortable with React and prefers it for building component systems, how do we make that feasible and good for websites? I'm not claiming these problems were always solved in the best way. I'm saying they were positions in a long-running argument about trade-offs.

But we are not in the same place as in 2008. Your "server" is a very different thing now, most probably stateless and hiding behind someone's confusing pricing page.

And you have a new constraint to think about to do your work that’s unlike anything we had before: tokens and inference. And now you need to learn new abstractions like harnesses and agentic loops to get your job done as quickly as the others.

AI solidifies web tech, but creates new itches

We're entering a phase where we have to think about how agents experience the web, and how we deliver content and functionality to them so they can operate on behalf of their users. Building agentic experiences brings a load of new itches, like chatbot design, durable processes, and figuring out what a "page" even means when the visitor isn't a person. The frameworks for this are already being poured, like Vercel's eve and the Gatsby founders' Mastra. As mentioned above, an agent in eve is a directory of files with an instructions.md at its core. The newest frontend artifact of 2026 is a Markdown file written for a machine to read.

AI both solidifies the tools we have (it gravitates toward what it was trained on, which is the web as it was) and creates entirely new premises for what tooling we need and what a web experience is expected to be (chatbots alone are teaching people to expect interactive widgets, voice modes, generative UI). The Descent's own field kit recommends React and Next.js partly because that's what the AI tools reach for by default. So the model recommends what the corpus contains, the recommendations refill the corpus, and yesterday's sediment compacts into tomorrow's rock.

A field kit of questions

If I were packing a field kit for what's coming, mine would hold questions. Where do the words live? Who changes them without you? What survives when the stack around them dies? Who, or what, is reading them that isn't a person? The first three would have made sense in any year since 1998. The fourth is new, and I suspect it's most of the kit now.

There's a fair objection to close on. Haven't I just done the same thing, picked the layers that flatter my argument? A CMS guy writes the history where CMSs turn out to be a missing continent. Guilty. I skipped Web Components, the accessibility movement, and nearly everything that happened outside the English-speaking web. I’m sure you can tell me on the socials (please do!).

But "every tool is scar tissue over a real wound" is a universal claim, and universal claims die to counterexamples; Flash, ThemeForest, and the WHATWG walkout are three. My history only needs to show the other motors running. And the act of telling it proves the rest, because which history of tooling you get depends on where the teller stood, what they were paid to care about, and what their culture celebrated. And I guess, what prompts they put into the LLM to get that story out.

A compressed history gets corrected by witnesses, and this post is one more. Some of us were watching. More of us should say what we saw. ✌

Notes

  1. 1.Yes, I hand-picked this one.
Be the first to linger on this prose

Down the rabbit hole