
The server is back: why SSR and hypermedia beat SPAs in 2026
A manifesto. How the web used to work, why we threw it away for ten years, and why server-rendered HTML with HTMX is the right default in 2026. State on the server, simple beats clever, the old web was right all along.
In 2009 the web worked like this. The browser asked the server for a page. The server rendered HTML, sent it over the wire. The browser displayed it. When the user clicked something, the browser asked the server for the next page. The server rendered HTML, sent it over the wire. The browser displayed it.
The web was fast, simple, and recognizably the web.
Then a decade of single-page applications happened. We shipped megabytes of JavaScript to the browser, rewrote routing, state management, form handling, and HTML rendering on the client. We invented hydration, suspense, streaming server components, and edge runtimes. We added 47 build tools to compile our 47 languages back into the three languages browsers actually run.
The result is that most “modern” SaaS landing pages today are slower, less reliable, and harder to maintain than the PHP apps they replaced.
This post is the long version of “I told you so”, and also the case for going back to the way things worked, with one new ingredient that closes the gap.
What we threw away
The 2010 web stack was straightforward.
- The server held state. Sessions, user data, business logic, all server-side.
- The server rendered pages. HTML, templated, sent over the wire.
- The browser displayed HTML, submitted forms, followed links. That was its job.
- Each request was independent. Stateless on the wire.
- Caching was easy because URLs were resources.
- SEO was easy because Google saw the same HTML you did.
- The “front end” and “back end” were the same thing.
This worked. Every successful web app from 1995 to 2014 was built this way. eBay. Amazon. Wikipedia. Stack Overflow. Reddit (the old one). All built on server-rendered HTML.
Then we collectively decided this was not “modern” enough.
What we built instead
The SPA era replaced “the server sends HTML” with “the server sends JSON, the browser turns it into HTML.” This sounded like a small change. It was not.
To turn JSON into HTML in the browser, you need:
- A JavaScript framework (React, Vue, Angular, Svelte, take your pick).
- A bundler to package your framework code (Webpack, Vite, esbuild, Rollup).
- A router because the browser cannot route anymore (React Router, TanStack Router, Next.js routing).
- A data-fetching library because
fetchis not enough (React Query, SWR, tRPC). - A state management library because
useStateis not enough (Redux, Zustand, Jotai, MobX). - A form library because forms are now JavaScript (Formik, React Hook Form, Conform).
- A validation library because the browser cannot validate anymore either (Zod, Yup, Joi).
- A toast library, a modal library, a date picker library, an autocomplete library.
- A meta-framework to glue it all together (Next.js, Remix, Nuxt, SvelteKit).
- Server-rendering bolted back on, because we noticed Google could not see our pages.
- Hydration to reconcile server-rendered HTML with client-side state.
- Streaming server components to fix the hydration problems.
- Suspense boundaries to fix the streaming problems.
We did all of this so the browser would not have to ask the server when the user clicks a link.
This is, in hindsight, a wild thing to have done. The browser is very good at asking the server when the user clicks a link. We invented HTTP for it.
The cost of “modern”
Every line of this is real:
- A typical SaaS marketing page in 2026 ships hundreds of kilobytes to over a megabyte of JavaScript, mostly framework runtime that the page does not need. The page underneath is a list of features, a pricing table, and a signup form.
- Time-to-interactive on a mid-range mobile is often multiple seconds even for trivial pages, because the framework has to boot before anything responds. Server-rendered pages of the same content respond as fast as the network round-trip allows.
- A typical Next.js app pulls in hundreds to thousands of transitive npm dependencies. A Go web app pulls in a fraction of that, mostly from the standard library and major orgs. The npm supply chain has had multiple worm-grade incidents in the last 12 months. (See Javascript is a security liability.)
- Search engines run JavaScript, but on a delay and with limits. Server-rendered HTML is still indexed instantly and completely. AI search engines often cannot run JavaScript at all.
- Hydration mismatches are a category of production bug that simply does not exist in server-rendered apps. Every React shop has a story about chasing one.
- The “framework choice” itself has become a hiring filter. “We use Svelte” eliminates a third of available React developers and vice versa. Server-rendered Go does not have this problem.
We accepted all of these costs in exchange for… what, exactly?
What SPAs were actually for
To be fair to the SPA era: SPAs were the right answer for some kinds of apps.
- Figma, Linear, Notion. Deeply interactive client apps where the entire UI is the product.
- Google Docs, Google Maps. Real-time collaboration and continuous updates.
- Discord, Slack. Persistent connections, voice and video.
- 3D editors, video editors, design tools, IDEs.
For these apps, the SPA model is genuinely the right choice. The interaction loops are tight enough that round-tripping to a server would feel slow.
Then someone said “if SPAs work for Figma, they should work for our static-content SaaS landing page with three forms and a billing flow.” And we have been paying for that mistake for ten years.
Most web apps are not Figma. Most web apps are “list, detail, form, submit.” For those, server-rendered HTML was always the right answer. We just stopped letting ourselves do it.
What HTMX changed
For a long time, the “go back to SSR” argument had a real flaw. The PHP and Rails apps of 2010 did feel slow. Every interaction was a full page reload. Modern users expected instant feedback on every click. The SPA, for all its costs, did deliver that.
HTMX is the missing piece. It is a 14 KB JavaScript file that teaches your browser a handful of new HTML attributes:
hx-get,hx-post,hx-put,hx-deletefor AJAX requests.hx-targetfor “what part of the page should this update.”hx-swapfor “how should it update.”hx-triggerfor “what event triggers the request.”
With HTMX, you write this:
<button hx-post="/posts/42/like" hx-target="this" hx-swap="outerHTML">
Like
</button>
The server responds with HTML. HTMX swaps it into the page. No reload. No JSON. No JavaScript written by you.
That is the SPA-grade interactivity you wanted, with the server-rendered architecture you needed. The thing the 2010 web could not give you. The thing the 2020 SPA was overengineered to give you.
State belongs on the server
Here is the architectural principle that the SPA era forgot.
The server is the source of truth. The UI is a view of the server.
Every time you put state in the browser, you create a synchronization problem. The browser thinks the user has 3 unread messages. The server says 5. The user opens another tab. Now you need WebSockets, optimistic updates, conflict resolution, a state reconciliation library, and four hours of debugging.
If state lives on the server and the UI is a view of the server, this problem does not exist. The user clicks “refresh,” the server tells them what is true. The user clicks “mark as read,” the server updates, sends back the new HTML, the browser displays it. Single source of truth, single direction of data flow, no synchronization.
This is the same principle Unix figured out in 1970, that databases enforce, that event sourcing is trying to recover. The SPA era was an anomaly. The pendulum is swinging back.
“But what about offline”
A reasonable question. The honest answer: 99% of web apps do not need offline.
- Your CRM does not work without the internet. That is fine.
- Your invoicing tool does not work without the internet. That is fine.
- Your indie SaaS dashboard does not work without the internet. That is fine.
For the 1% that do need offline, build a hybrid. Use service workers for the offline cache. Use IndexedDB for local data. Use a sync engine when you reconnect. This is real work, and it is the same real work you would do in any architecture. The SPA does not magically solve it.
If your product is “spreadsheet that works offline,” yes, build an SPA. If your product is “this website where users do things and pay you,” server-rendered is fine.
“But the developer experience is worse”
This used to be true. In 2026, it is not.
templgives you JSX-style templates with full type safety and IDE support.- HTMX has a tiny API surface. You learn it in an hour.
- Tailwind gives you the styling experience you had in CSS-in-JS without the runtime cost.
- The Go (or Elixir, or Rails, or Django) standard library does most of what npm packages do.
- AI coding tools handle server-rendered stacks at least as well as they handle React. Some patterns better (because the surface area is smaller).
- Deploys are a single binary. No build server, no edge runtime, no “did the right environment variable propagate to the serverless function” debugging.
The first hour of “going back to SSR” feels strange. By the second hour it starts to feel obvious, and the next year is faster than any year you have had on a SPA.
“But what about the team”
Hiring. The real argument.
A React-heavy team will resist the move. Their muscle memory is in useEffect and useQuery. Their portfolio is in client-side state libraries. Asking them to write Go and templ feels like a demotion. It is not, but it feels that way.
There are two answers.
- If your team is committed to React, stay on React. Use Next.js with server components and minimize client-side JavaScript. You can do most of the SSR pattern inside React if you discipline yourself. It is harder than just using Go, but it is feasible.
- If you are building a new product, you do not have a team yet. Pick the stack that makes the next hire easier. Go developers exist. They are also less scarce than they were in 2018, partly because the AI coding workflow rewards languages that AI handles well, and Go fits that.
The “what about the team” argument is real. It is not the dominant argument for greenfield.
What the 2026 web actually looks like
Take a hard look at the web in 2026. The fastest, most reliable, most accessible sites are:
- Hacker News. Server-rendered HTML. 10 KB pages. Faster than anything you have shipped on Next.js.
- Wikipedia. Server-rendered HTML. Loads instantly on dial-up.
- Stripe documentation. Server-rendered, with carefully scoped islands of interactivity.
- Tailwind CSS docs. Server-rendered, lightning fast.
- GOV.UK. Server-rendered, Web Vitals: green across the board.
- This blog. Server-rendered Go and templ.
The fastest things on the web in 2026 are not Next.js apps with elaborate streaming. They are sites that figured out that HTML is the right format and the server is the right place to render it.
The HOWL stack
A community of practitioners has started calling this approach HOWL: Hypermedia On Whatever’s Left.
- Hypermedia = HTML with semantic links and forms. The original web protocol.
- Whatever’s Left = whatever language you already know. Go, Python, Ruby, Elixir, PHP, .NET, Java, Crystal. They all work.
The pattern is the same in any language: server-rendered HTML, HTMX for interactivity, Tailwind for styling, a small JavaScript file when you need something HTMX cannot do.
The HOWL stack in 2026:
| Language | Server stack | Notable apps |
|---|---|---|
| Go | templ + Echo/Gin/net.http + HTMX | This site |
| Python | Jinja/Django + HTMX | Many internal tools |
| Ruby | Rails + Hotwire (similar to HTMX) | Basecamp, HEY |
| Elixir | Phoenix + LiveView | Fly.io dashboard |
| PHP | Laravel + Livewire (similar to HTMX) | Many internal business apps |
All of these stacks are renaissance-grade alive in 2026. None of them require a 2 MB JavaScript bundle. All of them produce production-grade SaaS.
The case in one paragraph
For the kind of web app most SaaS founders are actually building (list views, detail views, forms, dashboards, content sites, marketing pages, blogs, docs), server-rendered HTML with HTMX is faster to build, faster to run, faster to deploy, cheaper to host, easier to maintain, more accessible, more SEO-friendly, more reliable in low-bandwidth environments, and friendlier to AI coding tools than any SPA-based alternative.
The SPA era was a ten-year detour. The pendulum is swinging back to the architecture that worked from 1995 to 2014, with one new ingredient (HTMX) that closes the only real UX gap.
The tools are ready, the community is healthy, and your competitors are still shipping 2 MB of JavaScript per page. That gap is not closing.
Where to start
goilerplate is the production Go boilerplate built on exactly this stack. templ for templates, HTMX for interactivity, Tailwind and templUI for styling, Go for everything else. Auth, payments, blog, docs, email, SEO, security headers, deployment, all wired up out of the box. The founder story is here if you want the background. New features and blocks ship every week, lifetime updates included.
If Go is not your language, the same stack exists for Python (Django + HTMX), Ruby (Rails + Hotwire), Elixir (Phoenix + LiveView), PHP (Laravel + Livewire), and a handful of others. Pick the one that fits your team.
If you have been on the SPA treadmill for years and you feel like something is off but you cannot name it, this is the something. Try the HOWL stack for one weekend project. You will not want to go back.
The server never really left. We are just collectively remembering why we built the web on it in the first place.