SPAs make sense when your users have long sessions in your app. When it is worth the pain to load a large bundle in exchange for having really small network requests after the load.
Smooth transitions are a nice side effect, but not the reason for an SPA. The core argument of the article, that client-side routing is a solution for page transitions, is a complete misunderstanding of what problems SPAs solve. So absolutely, if you shared that misunderstanding of SPAs and used them to solve the wrong problem, this article is 100% correct.
But SPAs came about in the days of jQuery, not React. You'd have a complex app, and load up a giant pile of jQuery spaghetti, which would then treat each div of your app is its own little mini-app, with lots of small network requests keeping everything in sync. It solved a real problem, of not wanting to reload all that code every time a user on an old browser, with a slow connection, changed some data. jQuery made it feasible to do SPAs instead.
Later, React and other frameworks made it less spaghetti-like. And it really took off. Often, for sketchy reasons. But the strongest argument for SPAs remains using them as a solution to provide a single-load of a large code bundle, that can be cached, to provide minimal network traffic subsequent to the load when the expected session time of a user is long enough to be worth the trouble of the complexity of an SPA.
SPA is not only about seamless transitions but also being able to encapsulate a lot of user journey on the client side, without the need of bothering server too much.
Let me give you an example - one of my biggest gripes about web ux is the fact that in 2025 most shops still requires you to fully reload (and refetch) content when you change filters or drill down a category.
A common use case is when you come to a shop, click on "books" (request), then on "fantasy" subsection (another request), realize the book you're looking for is actually a "sci-fi", so you go back (request, hopefully cached) and go to "sci-fi" (another request).
It's much better ux when a user downloads the whole catalogue and then apply filters on the client without having to touch the server until he wants to get to the checkout.
But it's a lot of data - you may say - maybe on Amazon, but you can efficiently pack sections of most shops in data that will enable that pattern in less kilobytes that takes one product photo.
I've been building web apps like that since ca. 2005 and I still can't understand why it's not more common on the web.
I don't know what universe this SEO-consultant author lives in. The author gives Next & Nuxt as an example of the kind of frameworks going against his prescription, but that is so wrong.
1. Next won the war in the west, big time. Very very big time. Whenever people talk about new React apps they inadvertently mean Next. On the Vue side Nuxt is the default winner, and Nuxt is just the Next of Vue. That means that by default, by reflexive instinct, people are choosing Next and MPA as their strategy. If you want to correct the overly extreme pendulum motion then you should be telling people to try out SPA. The last 8 years has been a feverish push for MPA. Even the Facebook docs point straight to Next, totally deprecating Create React App. This is also Facebook ceding their battle to Next.
2. Whenever people complain about the complexity of Next, they are complaining about the difficulties of cutting edge MPA strategy, which evolves on a year to year basis. SPA on the other hand is a story that has frozen in time for who knows how many years. Almost a decade?
3. Doing MPA is strictly harder than doing SPA, much much harder. You have to observe the server/client distinction much more closely, as the same page may be split down the middle in terms of server/client rendered.
4. If you're writing an SPA and want to be more like MPA and load data at the time of hitting a user-navigable endpoint, that's on you, benefits and costs and all. You can also load data with anticipation so the client navigation is basically instant.
5. For every sexy SEO-able front-facing property you're going to have many teams with internal apps or dashboards backing that front-facing property. That's where many React devs are employed. Do not unnecessarily take on burden because you're so eager to ship the first "frame" of your app in a perfect way.
The point of SPAs was never page transitions. I can’t name a single major SPA that does good page transitions, can you? They all just replace the content. And to take a popular SPA framework as an example, it’s almost impossible to do page transitions in Next.js because of the way routes are loaded. I know this because I added proper page transitions to Next.js and it has been an absolute nightmare.
There are two good reasons for SPAs that I can see:
1. Your app probably needs interactivity anyway; for most apps, it’s not just going to be HTML and CSS. Writing your app in some unholy combination of React and HTML is not fun especially when you need to do things like global state.
2. Loading the structure of pages up front so that subsequent data loads and requests are snappy. Getting a snappy loading screen is usually better than clicking and getting nothing for 500ms and then loading in; the opposite is true below I’d say 100ms. Not needing to replace the whole page results in better frontend performance, which can’t really be matched today with just the web platform.
Basecamp has probably invested the most in making a fairly complex webapp without going full SPA, but click around for like 30 seconds and you’ll see it can’t hold a candle in performance to SPAs, never mind native apps.
With that said, I agree that I’d want the web to work more like the web, instead of this weird layer on top. All the complexity that Next.js and SPAs have added over the years have resulted in more responsive but sometimes more tedious-to-build apps, and gigantic bundles. I just don’t think you can match the performance of SPAs yet with just HTML.
I think this article is unfair to SPAs. SPAs are a lot more effort, but they are better. For a long time they have been the only way to "make it feel like an app." (I think the author says "make it feel like an app" because they know we all resent app fatigue, all the apps we have to download that should just be web sites, but I think we also all know that when something really is an application, it's rare for a "web app" to match the experience of a local native application, and an SPA is the only way to make a sincere attempt.)
The comparison of bloated SPAs with lean web sites is bogus. If someone takes the effort to make their web site lean, they'd do the same with an SPA. If someone makes a slow, bloated SPA with megabytes of Javascript, they'd make a slow, bloated web site with megabytes of Javascript. I think we've all seen enough of the web to know this is true.
I click on articles like these because I've seen the effort that goes into a good SPA, and I'm interested in anything that would allow people to deliver an equivalent experience with less effort. All I see here is a tiny bit of cosmetic polish. Polish is appreciated, but this doesn't seem like something that would tip the balance between building an SPA or not. Am I missing something?
Lots of pushback here in the comments. But I can't think of the last time I enjoyed using a SPA website over a multi-page one. The initial loading feels delayed, the page scrolling feels unnatural and jarring (completely opposite of how a native app feels).
Also, one of my banks recently changed their old website to a new SPA one. And it is now completely useless. It can't load information in time, so most of the forms are empty. You can't even go back because it is a SPA. So I can only log out, log in and try again. Kind of scary when you are handling a lot of money.
And it is not just one website. As I said I can't recall ever using a good SPA website. So yeah, I can't wait until they are all gone.
This argument is tired and ignorant. Try building linear.app without a SPA framework. The idea that "Native CSS transitions have quietly killed the strongest argument for client-side routing," is dubious at best.
This article is getting a lot of pushback from the SPA champions, deservedly so, but it makes some good points to. I can’t be the only one, but I myself am getting very tired of the amount of websites where I have to sit and look at a skeleton loading for way too many seconds, then the data loads and it looks nothing like the skeleton. There is an over abundance of really crappy SPAs out there. Sorry not sorry
I swear if I see another "SEO" guy or some rando web dev who joined the workforce after Covid complaining about SPAs by misrepresenting it, I'm gonna explode.
As someone who's been developing web apps since the 2000s, let me tell you the origin of SPA has few things to do with the "false promise of SPAs" he listed, but largely due to companies in the late 2000/early 2010s wanting to go "mobile first". This usually meant they still had a desktop second somewhere, which implied they were architecting the entire system to completely separate the frontends and the backend.
Before, what web devs meant by frontend was essentially server-side rendered HTML templates with perhaps a little bit of jQuery running on the client-side. Now, since mobile and desktop web apps are to share some business logic and the database somehow, people had to rediscover REST by reading Roy Fielding's Phd dissertation that inspired the original HTTP. This meant now every company was moving to service-oriented architecture and started exposing their backend APIs onto the open internet so their mobile apps and SPAs running in the browser can share the same APIs. This was a cost saving measure.
This period also coincided with the steady decline of full-stack webapp frameworks like Ruby on Rails and Django because for a couple of years, these frameworks had no good ways to support an API only applications. Django hadn't even reached 1.0 back then. This was a time when NodeJS was really starting to pick up momentum. Once people had started being more comfortable with JS on the server-side, lots of people suddenly realized they could push a lot of business logic to increasing powerful desktop browsers and phones, application hosts people now call "edge devices".
This is the true impetus of SPA. How is CSS going to kill this need?
SPAs are not about view transitions. TFA implies that fancy transition is important between pages (wrong!) and blames a "CMO" or "brand manager" rather than challenging their own preconceptions and exploring the value an SPA does add:
- excellent frameworks for client side logic (interactivity)
- separation of concerns (presentation logic vs. backend)
- improved DevEx => inc. speed of development => happiness for all
The sad thing is that an article like this will get plenty of eyeballs due to comments like my own adding to the algo, but it should have never made it above the fold.
For me the promise of SPAs has nothing to do with fluidity and all to do with having a separate data API and separate frontend (that can be native or web or both)
That’s why I don’t like SSR mixed with client side rendering. Either do a website or an app.
SPAs are _applications_ folks. Just like app-apps are made -- spas are apps for the browser. SPAs in themselves are not complicated. State in an app is complicated. This is such a tired misunderstanding.
I'm not a fan of the SPA, or at least in practice, but there is something very attractive about going with a solution that everybody knows.
At work we are building a new "website like" frontend and it is a SPA (that internally operates as a MPA) built with React. The main reasons are we: know this setup well and know when hiring we will find people who know this setup as well. Beyond that, it will allow us to build out more application like features in the future if needed.
This approach has been popular in the industry for over 10 years now. Whereas most of the current discussion and tech on the frontend feels like churn and betting on the next thing. A lot of people just want tools that are mature and can get the job done regardless of them being the best tool under specific criteria.
There's still value in web applications what can perform most of their operations client-side, when feasible. Lots of websites seemingly operate under the assumption of "If the client manages to connect to the server once, then surely it can maintain a stable, low-latency connection in perpetuity." This renders those websites unusable on flaky connections or with very high latency. Of course, plenty of SPAs are guilty of using 15 million unnecessary round-trips, but I worry that the current SSR-everywhere push will worsen this effect.
I don’t want to write an article but I think when SPAs are called for they are the least worst option.
Usually I want to ship an app to customers, but for that I need an app the targets Apple platforms, hopefully I can built it to target iOS, iPadOS and MacOS but maybe those are three different apps. I need an app that targets Android. I also need an app that targets Windows, and I need a linux app.
Then I need to distribute all those apps, so I need to get onto the AppStore for MacOS, the play store for linux, and whatever Huawei/other Chinese manufacturers use, and whatever amazon uses, and probably have an “official” APK available for stuff like fdroid.
I need a windows installer, maybe a portable package for windows, and get onto MSStore (which will then cover winget).
I need to pick some collection of linux distros to target, usually targeting having a deb release and rpm can be good enough. And you can build an “installer” yourself if you are so inclined.
Or I could just ship an SPA, I had to build out the same servers if the data was not local anyway.
It's incredible to write an article about UX with a main argument of "this way is as good as that way" without visual examples to prove they actually behave the same.
I see some people claim that client-side routing isnt the strongest argument for SPA:s. And that is probably true from a technical point of view. However, lots of times users/clients want that even if they dont care about the rest (which is why I love how easy HTMX and Astro make it to add client side routing on top of a normal MPA).
This reads more like "ditch Next.js" for traditional SSR.
A good SPA has a lot of benefits. Because it can be interactive like a native app. It can only use those benefits, if it is interactive to some extent (like gmail or google docs). Smooth navigation is a very bad reason for picking a SPA.
It's time for sending HTML rendered on server with CSS, and JS for enhancement only to kill the SPA.
I'm not talking about this from a technical standpoint, though there are many reasons that in most cases this is the best technological fit.
I'm talking about this from the position of "what I want to use". I'm sick of loading and navigting overly JS heavy, overly styled, fragile "apps". When I encounter a "proper" website that loads fast, and I can understand easily it's like a breath of fresh air.
What counts as "SPA" and what's an "MPA"? I've got a NextJS site (my personal website, you can probably find it given you know my last name and that I'm in the UK) that renders pretty much everything server-side. Technically it's still an SPA because if you turn on Javascript it'll load RSC and do client-side navigation.
If you turn off Javascript? Pages with client-only components (like the 100% client-rendered QR code generator) will show their fallback, everything else will load and render perfectly -- if a little less quickly -- than if you let Next do its thing. It's all rendered into the HTML, and it's actually more effort to not render components on the server. Progressive enhancement for the win!
It's worth noting that the Speculation Rules API and the View Transition API are not stable in Firefox and therefore aren't supported by all major browser.
CSS, URLs, links, forms, POST-Redirect-GET, page reloads. Efficient and user friendly on the modern web. HTML & browsers have smoothed out a lot of rough edges.
The View Transitions API is beautiful and I can't wait for it to become widely available.
I've soured on SPAs in the past few years. So much more can be done with standards than people realize. SPAs were best for specific use cases but we made them the default for everything. Marketing pages are built in React! Basic pages with marketing copy have a build step and require hundreds of megabytes of dependencies.
Like the author I've transitioned to a mantra of "let the web be the web."
But we have a whole generation of developers and designers that have come of age with SPA and mobile-like ux as standard. Getting everyone back to basics and understanding hypermedia, markup languages and cascading styles is a big ask.
I was completely unaware of view transitions and speculation rules. All of my products are server rendered for speed and simplicity. It’s amazing how snappy the interface is when your pages just load quickly because your software is performant. These seem like a great way to add an extra 10% of flavour.
I once worked at a place where (for involved reasons not worth rehashing for this conversation) some of the backoffice, admin pages got rewritten in SPA fashion, after they had already been written in server-side fashion. It was an accidental experiment that showed me that the backend code did not decrease in size, whereas the frontend ballooned up to the same size as the backend (for fairly simple functionality even).
Now, this means you will need approximately twice as many developers. On the plus side, more work gets done on the client-side, so you probably need fewer servers for your billion users, and you may save in servers (and sysadmins) more than it costs you in developers to handle approximately twice as much code.
Except...99.9% of the shops using SPAs don't (and never will) have enough traffic for that tradeoff to make sense. The devs want (or at least wanted, back in the day) to go work at a company that did, so they wanted to use tools that would make sense if you're Facebook-sized. But, for the great majority of shops that made SPAs, there was no good reason to do so. This isn't Facebook's fault, but it is a reason why SPA's are annoying to so many people; they are almost always used in places that don't need them, and shouldn't be using them, in order to pad out a resume.
On one hand, SPAs took off and became massively popular. On the other, I’m still curious why PWAs—especially the kind with service-worker-powered offline access—never really did. I don't like SPAs only if I find them bloated and with a messed up browser history that back button moves you out of the website.
Imagine an e-commerce site that lets you review your order history and product pages offline (even if a bit outdated). That kind of experience feels genuinely useful—much more so than the "you're offline, here’s a cute dog (I love the pictures though)" fallback most sites provide.
Over the weekend, I experimented with service workers for the first time (assisted by Vibe coding). My initial impression was honestly a bit magical—“this website works offline, unlike most mobile apps these days that are just WebView-wrapped SPAs and crash offline.” [1]
That said, debugging was rough. Vibe coding output had subtle issues I found hard to untangle as a newcomer, cache saved v/s cache matching was being done incorrectly in the code, which LLM wasn't able to point out (cors/non-cors requests had issue).And Chrome’s DevTools made debugging manageable, but Firefox’s service worker support felt clunky in comparison (personal take).
Curious if others feel the same—are PWAs underused because of DX hurdles, lack of awareness, or just industry momentum around SPAs?
I strongly disagree with this. SPA has its place and a very important one. It is not just about replacing JS animations with CSS animations. Of course it depends on the use case - SPA makes little sense in many cases and a lot of sense in few. But it still has it's stable place.
From my own point of view and experience, SPA makes the most sense when you do not want to bundle backend and frontend together in your server code. Having a separate FE and BE with clearly set API(json) is very important in many many many cases and it allows you to use the same BE for different FE, like desktop website, mobile website, desktop client(electron), mobile application... trying to do this on the server would be hell. Also worth mentioning is that if you want to make changes in your FE, you have to bring down you BE in order to deploy them, whereas if you have BE and FE separated, you can deploy the FE without any downtime.
There is a lot more that could be said but the main point is that moving data rendering into FE and letting BE just serve raw data is the way to go in many situations.
We have been moving computation between FE and BE for decades now, but I think the tech is now sufficient to not force us to pick one over the other but chose what works best.
Personally, I think that rendering the UI on BE is archaic and should be handled on the client via some bundled thin client code, ala SPA. So I will always prefer client-rendering over server-rendering, no matter the setup.
PS: You might be interested in https://data-star.dev/ which came out of dissatistfaction with HTMX and I think will be the way to go about bridging FE and BE in the future.
Sounds like the major complaint here is trying to make the web into something it's not. It's something like 17 years since the iPhone app store. Web apps were not comparable to native apps then, and while they've made progress, web UX is still much poorer than a good native app. The Youtube mobile app has its problems but is so much better than the web interface.
Native and web have different strengths, that's ok.
> The reason SPAs became the default wasn’t because they were better. It was because, for a while, they were the only way to deliver something that felt fluid.
A lot of people are responding with other technical considerations that may lead you to consider using an SPA pattern. But, note that the article is about responding to the stakeholder's request that it should 'feel like an app', and his point is that you can make it feel like an app without being an SPA. Non-technical stakeholders rarely bring up deep technical considerations, they almost always talk about what something should feel like. So, I think his argument, while unlikely to work on anybody, is valid.
The thing about SPAs is that computation can be done in the customer's machine. That usually makes it worse for everyone, both devs and users (although sometimes it doesn't). I personally believe that we can create better experiences routing more pages with more imagination, but at times this industry is quite vocal on what "user expectations" are.
The main premise of this article is that SPA frameworks are primarily about transitions. This is yet another passionate argument built on a false foundation.
My SPA navigation solution is just simple CSS toggle of display none/block and then force it on page load if there is a matching URL fragment. Total JavaScript to make this SPA navigation is about 20 or so lines of JS. Everything else is CSS and WebSockets. The state management is almost as simple.
I’d like to add to the reasons for why you want an SPA over something with SSR:
* You have a large number of users compared to your resources and you can’t afford for your user base to always hit your server. Comparatively, deploying API-only apps is far cheaper when you’re resource-starved (eg early stage startup).
* You don’t care about SEO, for example you’re building internal tooling. You then don’t need to care about hydration at all. Much simpler to separate concerns (again esp at the beginning).
* Offline mode (eg PWA or reusable code in Electron) or cases where you want to be resilient to network failures. In the case that your app is dependent on the server for basic functionality like navigation, you can’t support any type of offline mode.
No, you found some tradeoffs and decided that the drawbacks are worse than the advantages. If industry disagrees, they tend to have their reasons, but as we love being tortured artists and really feeling our individualism, offbeat hot takes are always in demand.
Most of my personal app projects are SPAs, because it’s easy to just pop some static files in my static file server and serve a whole app with routing and functionality without having any server logic. Way simpler to maintain, since I can just sync my ‘apps’ dir and all my mini-projects are deployed.
I agree. What is more, you can even use HTMZ instead of JS frameworks and Pure HTML Out-Of-Order Streaming using Declarative Web Components: https://github.com/niutech/phooos
Everyone is completely missing the point of this article, which I find amusing and terrifying in equal measure.
He is _not_ talking about a SaaS dashboard SPA. He's talking about marketing sites and other content heavy stuff like blogs, landing pages, etc. It mentions this in many places if you go past the headline.
He is completely correct. SPAs should not be used for marketing sites full stop. Perhaps there are some edge cases where it may make sense (though I cannot think of any) but in general, if you are building anything that resembles a blog or landing page with nextjs et al you have done it wrong, close the code editor and start again. I'll give you a pass if you are developing an MVP of something and you need something up very quickly, but if you have any commercial traffic you will thank my later.
I have done a lot of audit work for this kind of stuff. Things I've seen:
10MB+ of React/JS libs to load a simple blog page
Putting images in the bundle, base64d. So badly that the page crashes OOM on many devices.
And my favourite of all time - shipping 120MB (!) of JSON down for a catalog. It literally loaded _the entire database_ to the front end to show _one_ product. It wasn't even an ecommerce site; it was literally a brochure of products you could browse for.
If full page requests have an ability to persist complex state, cache to the point of imperceptibility parts of the page that aren’t changing and never blink, I guess?
Not only SPAs are here to stay, but they're eating up native app on the desktop (with Electron et al., it's much easier to hire TS devs and write your app once rather than have different native codebases for Windows, Macos and Linux).
Now, I understand the argument that simple article-based websites shouldn't necessarily be SPAs. Page transitions are perfectly doable in pure HTML and CSS. But if you have less then trivial local state and complex + specific components, forcing the MPA pattern will only complicate your codebase.
what a nonsensical title, clearly written by people that only program skins around applications instead of applications themselves. CSS and SPA do not even solve the same problem.
I'm sure there exist (foolish) efforts to make CSS somehow able to do some UI logic, but that is never a good idea. CSS is a poorly made/overly complex spec that deserves to die. It's too late to make that argument unfortunately, but to want even more of CSS in the modern web stack is kinda lunatic.
I support a lot of this, especially for sites that don't need to be applications... but SPAs aren't just about flashy transitions and persistent elements. If you've got a bunch of live data you want to change on interaction an SPA is still hard to beat.
Ok, now try to implement a tree component in an MPA. But not a crappy tree component that only opens one branch at a time, like in a page from 1998. A tree component that remembers the open/close state of each branch.
Before the SPA, these were common issues. That’s why there were a gazillion Java server pages frameworks to solve them. You also have frameworks that tried to encode the UI state in some way. My favorite was Seaside, which used continuations to store the UI state.
The following article should probably be titled “It’s time for modern bloggers to kill the clickbait titles” and discuss the trade-offs of each architectural decision more balancedly.
Once again people totally miss the point of SPA. What does SPA stand for? Hint, there is no website in there.
Id argue all the grousing of spa is because people made websites as apps when they should have been websites instead.
Btw view transitions are pretty slick and require zero js to get snazzy transitions.
Edit: there are some significant limitations with view transitions around performance and a few other gochas I should mention when they are used with pure css. I still love em tho.
I wonder if my slop radar is oversensitive to em dashes and the construction: “it’s not just about foo, it’s about bar” because this post seems human written but the indicators are flashing
> Native CSS transitions have quietly killed the strongest argument for client-side routing
What? This guy wanted to show off how much he knew about CSS and decided the only way to do it was completely make stuff up about a hot-button topic in webdev.
>The reason SPAs became the default wasn’t because they were better. It was because, for a while, they were the only way to deliver something that felt fluid – something that didn’t flash white between pages or jank the scroll position.
This was NOT the reason why.
SPAs are better because it offloads as much processing as possible to EDGE cpu's. The idle compute among all users aggregates to a massive amount so might as well use it and minimize html construction and routing on the server side.
CSS is a mess for anything besides basic static layout. You can force it to do fancy things, but it's hacky and gives you code that doesn't really say what it does. You can do scss, sass, etc, but still eh.
> Build a site like a site. Use HTML. Use navigation. Use the platform.
Sure, but what about all the other problems that aren't solved by View Transitions? There's some truth to the fact that frameworks like Next.js has jumped the shark. But they're not solving the problems of _just_ the SPA.
SPAs and packaging your app inside a chrome container needs to die a hard death. Why is everything in 1 window. Why in 2025 can i not have multiple chat windows open?
Websites and apps that feel like quality are generally made by people who can achieve it. You'll get shit static sites or shit SPAs if you have shitty devs. It's not beyond reason. If you are shitty chef, your food is going be shitty. So yeah, here's the big secret about programmers:
They are mostly shitty
---
Interestingly, every landing page or website for recent AI apps have looked AMAZING. Designers and standard website developers are totally on point. It's just, crappy developers who can't create a rich experience on top of incredible design that's the issue. CSS is not going to fix what can't be fixed (some people are not supposed to be in this profession, but hey, it pays ... for another three or so years).
TL;DR: article means traditional websites with server navigation (now dubbed MPAs, multi page applications) have evolved positively with better handling of page transitions. But they choose to frame this idea by trashing SPA, while both MPA and SPA have a role to play.
It's time for modern CSS to kill the SPA
(jonoalderson.com)543 points by tambourine_man 16 hours ago | 327 comments
Comments
Smooth transitions are a nice side effect, but not the reason for an SPA. The core argument of the article, that client-side routing is a solution for page transitions, is a complete misunderstanding of what problems SPAs solve. So absolutely, if you shared that misunderstanding of SPAs and used them to solve the wrong problem, this article is 100% correct.
But SPAs came about in the days of jQuery, not React. You'd have a complex app, and load up a giant pile of jQuery spaghetti, which would then treat each div of your app is its own little mini-app, with lots of small network requests keeping everything in sync. It solved a real problem, of not wanting to reload all that code every time a user on an old browser, with a slow connection, changed some data. jQuery made it feasible to do SPAs instead.
Later, React and other frameworks made it less spaghetti-like. And it really took off. Often, for sketchy reasons. But the strongest argument for SPAs remains using them as a solution to provide a single-load of a large code bundle, that can be cached, to provide minimal network traffic subsequent to the load when the expected session time of a user is long enough to be worth the trouble of the complexity of an SPA.
Let me give you an example - one of my biggest gripes about web ux is the fact that in 2025 most shops still requires you to fully reload (and refetch) content when you change filters or drill down a category.
A common use case is when you come to a shop, click on "books" (request), then on "fantasy" subsection (another request), realize the book you're looking for is actually a "sci-fi", so you go back (request, hopefully cached) and go to "sci-fi" (another request).
It's much better ux when a user downloads the whole catalogue and then apply filters on the client without having to touch the server until he wants to get to the checkout.
But it's a lot of data - you may say - maybe on Amazon, but you can efficiently pack sections of most shops in data that will enable that pattern in less kilobytes that takes one product photo.
I've been building web apps like that since ca. 2005 and I still can't understand why it's not more common on the web.
1. Next won the war in the west, big time. Very very big time. Whenever people talk about new React apps they inadvertently mean Next. On the Vue side Nuxt is the default winner, and Nuxt is just the Next of Vue. That means that by default, by reflexive instinct, people are choosing Next and MPA as their strategy. If you want to correct the overly extreme pendulum motion then you should be telling people to try out SPA. The last 8 years has been a feverish push for MPA. Even the Facebook docs point straight to Next, totally deprecating Create React App. This is also Facebook ceding their battle to Next.
2. Whenever people complain about the complexity of Next, they are complaining about the difficulties of cutting edge MPA strategy, which evolves on a year to year basis. SPA on the other hand is a story that has frozen in time for who knows how many years. Almost a decade?
3. Doing MPA is strictly harder than doing SPA, much much harder. You have to observe the server/client distinction much more closely, as the same page may be split down the middle in terms of server/client rendered.
4. If you're writing an SPA and want to be more like MPA and load data at the time of hitting a user-navigable endpoint, that's on you, benefits and costs and all. You can also load data with anticipation so the client navigation is basically instant.
5. For every sexy SEO-able front-facing property you're going to have many teams with internal apps or dashboards backing that front-facing property. That's where many React devs are employed. Do not unnecessarily take on burden because you're so eager to ship the first "frame" of your app in a perfect way.
There are two good reasons for SPAs that I can see:
1. Your app probably needs interactivity anyway; for most apps, it’s not just going to be HTML and CSS. Writing your app in some unholy combination of React and HTML is not fun especially when you need to do things like global state.
2. Loading the structure of pages up front so that subsequent data loads and requests are snappy. Getting a snappy loading screen is usually better than clicking and getting nothing for 500ms and then loading in; the opposite is true below I’d say 100ms. Not needing to replace the whole page results in better frontend performance, which can’t really be matched today with just the web platform.
Basecamp has probably invested the most in making a fairly complex webapp without going full SPA, but click around for like 30 seconds and you’ll see it can’t hold a candle in performance to SPAs, never mind native apps.
With that said, I agree that I’d want the web to work more like the web, instead of this weird layer on top. All the complexity that Next.js and SPAs have added over the years have resulted in more responsive but sometimes more tedious-to-build apps, and gigantic bundles. I just don’t think you can match the performance of SPAs yet with just HTML.
The comparison of bloated SPAs with lean web sites is bogus. If someone takes the effort to make their web site lean, they'd do the same with an SPA. If someone makes a slow, bloated SPA with megabytes of Javascript, they'd make a slow, bloated web site with megabytes of Javascript. I think we've all seen enough of the web to know this is true.
I click on articles like these because I've seen the effort that goes into a good SPA, and I'm interested in anything that would allow people to deliver an equivalent experience with less effort. All I see here is a tiny bit of cosmetic polish. Polish is appreciated, but this doesn't seem like something that would tip the balance between building an SPA or not. Am I missing something?
Also, one of my banks recently changed their old website to a new SPA one. And it is now completely useless. It can't load information in time, so most of the forms are empty. You can't even go back because it is a SPA. So I can only log out, log in and try again. Kind of scary when you are handling a lot of money.
And it is not just one website. As I said I can't recall ever using a good SPA website. So yeah, I can't wait until they are all gone.
As someone who's been developing web apps since the 2000s, let me tell you the origin of SPA has few things to do with the "false promise of SPAs" he listed, but largely due to companies in the late 2000/early 2010s wanting to go "mobile first". This usually meant they still had a desktop second somewhere, which implied they were architecting the entire system to completely separate the frontends and the backend.
Before, what web devs meant by frontend was essentially server-side rendered HTML templates with perhaps a little bit of jQuery running on the client-side. Now, since mobile and desktop web apps are to share some business logic and the database somehow, people had to rediscover REST by reading Roy Fielding's Phd dissertation that inspired the original HTTP. This meant now every company was moving to service-oriented architecture and started exposing their backend APIs onto the open internet so their mobile apps and SPAs running in the browser can share the same APIs. This was a cost saving measure.
This period also coincided with the steady decline of full-stack webapp frameworks like Ruby on Rails and Django because for a couple of years, these frameworks had no good ways to support an API only applications. Django hadn't even reached 1.0 back then. This was a time when NodeJS was really starting to pick up momentum. Once people had started being more comfortable with JS on the server-side, lots of people suddenly realized they could push a lot of business logic to increasing powerful desktop browsers and phones, application hosts people now call "edge devices".
This is the true impetus of SPA. How is CSS going to kill this need?
- excellent frameworks for client side logic (interactivity) - separation of concerns (presentation logic vs. backend) - improved DevEx => inc. speed of development => happiness for all
The sad thing is that an article like this will get plenty of eyeballs due to comments like my own adding to the algo, but it should have never made it above the fold.
That’s why I don’t like SSR mixed with client side rendering. Either do a website or an app.
At work we are building a new "website like" frontend and it is a SPA (that internally operates as a MPA) built with React. The main reasons are we: know this setup well and know when hiring we will find people who know this setup as well. Beyond that, it will allow us to build out more application like features in the future if needed.
This approach has been popular in the industry for over 10 years now. Whereas most of the current discussion and tech on the frontend feels like churn and betting on the next thing. A lot of people just want tools that are mature and can get the job done regardless of them being the best tool under specific criteria.
Usually I want to ship an app to customers, but for that I need an app the targets Apple platforms, hopefully I can built it to target iOS, iPadOS and MacOS but maybe those are three different apps. I need an app that targets Android. I also need an app that targets Windows, and I need a linux app.
Then I need to distribute all those apps, so I need to get onto the AppStore for MacOS, the play store for linux, and whatever Huawei/other Chinese manufacturers use, and whatever amazon uses, and probably have an “official” APK available for stuff like fdroid.
I need a windows installer, maybe a portable package for windows, and get onto MSStore (which will then cover winget).
I need to pick some collection of linux distros to target, usually targeting having a deb release and rpm can be good enough. And you can build an “installer” yourself if you are so inclined.
Or I could just ship an SPA, I had to build out the same servers if the data was not local anyway.
A good SPA has a lot of benefits. Because it can be interactive like a native app. It can only use those benefits, if it is interactive to some extent (like gmail or google docs). Smooth navigation is a very bad reason for picking a SPA.
I'm not talking about this from a technical standpoint, though there are many reasons that in most cases this is the best technological fit.
I'm talking about this from the position of "what I want to use". I'm sick of loading and navigting overly JS heavy, overly styled, fragile "apps". When I encounter a "proper" website that loads fast, and I can understand easily it's like a breath of fresh air.
If you turn off Javascript? Pages with client-only components (like the 100% client-rendered QR code generator) will show their fallback, everything else will load and render perfectly -- if a little less quickly -- than if you let Next do its thing. It's all rendered into the HTML, and it's actually more effort to not render components on the server. Progressive enhancement for the win!
The concerns of SPAs and CSS are completely orthogonal.
I've soured on SPAs in the past few years. So much more can be done with standards than people realize. SPAs were best for specific use cases but we made them the default for everything. Marketing pages are built in React! Basic pages with marketing copy have a build step and require hundreds of megabytes of dependencies.
Like the author I've transitioned to a mantra of "let the web be the web."
But we have a whole generation of developers and designers that have come of age with SPA and mobile-like ux as standard. Getting everyone back to basics and understanding hypermedia, markup languages and cascading styles is a big ask.
Now, this means you will need approximately twice as many developers. On the plus side, more work gets done on the client-side, so you probably need fewer servers for your billion users, and you may save in servers (and sysadmins) more than it costs you in developers to handle approximately twice as much code.
Except...99.9% of the shops using SPAs don't (and never will) have enough traffic for that tradeoff to make sense. The devs want (or at least wanted, back in the day) to go work at a company that did, so they wanted to use tools that would make sense if you're Facebook-sized. But, for the great majority of shops that made SPAs, there was no good reason to do so. This isn't Facebook's fault, but it is a reason why SPA's are annoying to so many people; they are almost always used in places that don't need them, and shouldn't be using them, in order to pad out a resume.
Imagine an e-commerce site that lets you review your order history and product pages offline (even if a bit outdated). That kind of experience feels genuinely useful—much more so than the "you're offline, here’s a cute dog (I love the pictures though)" fallback most sites provide.
Over the weekend, I experimented with service workers for the first time (assisted by Vibe coding). My initial impression was honestly a bit magical—“this website works offline, unlike most mobile apps these days that are just WebView-wrapped SPAs and crash offline.” [1]
That said, debugging was rough. Vibe coding output had subtle issues I found hard to untangle as a newcomer, cache saved v/s cache matching was being done incorrectly in the code, which LLM wasn't able to point out (cors/non-cors requests had issue).And Chrome’s DevTools made debugging manageable, but Firefox’s service worker support felt clunky in comparison (personal take).
Curious if others feel the same—are PWAs underused because of DX hurdles, lack of awareness, or just industry momentum around SPAs?
[1]: https://ball-sort-game.vercel.app/
You can pay some upfront cost and have wildly more performant apps.
From my own point of view and experience, SPA makes the most sense when you do not want to bundle backend and frontend together in your server code. Having a separate FE and BE with clearly set API(json) is very important in many many many cases and it allows you to use the same BE for different FE, like desktop website, mobile website, desktop client(electron), mobile application... trying to do this on the server would be hell. Also worth mentioning is that if you want to make changes in your FE, you have to bring down you BE in order to deploy them, whereas if you have BE and FE separated, you can deploy the FE without any downtime.
There is a lot more that could be said but the main point is that moving data rendering into FE and letting BE just serve raw data is the way to go in many situations.
We have been moving computation between FE and BE for decades now, but I think the tech is now sufficient to not force us to pick one over the other but chose what works best.
Personally, I think that rendering the UI on BE is archaic and should be handled on the client via some bundled thin client code, ala SPA. So I will always prefer client-rendering over server-rendering, no matter the setup.
PS: You might be interested in https://data-star.dev/ which came out of dissatistfaction with HTMX and I think will be the way to go about bridging FE and BE in the future.
Native and web have different strengths, that's ok.
So they were better.
Absolute disagree with the way you're arguing though.
YouTube serves hundreds of MB payloads to serve information. Even a bloated SPA is tiny in comparison.
Although, I think YouTube is also an SPA.
Some websites serve hundred MB payloads to show a hero video.
Why is JS optimization the great evil when there is often so much more waste in media or design choices?
My SPA navigation solution is just simple CSS toggle of display none/block and then force it on page load if there is a matching URL fragment. Total JavaScript to make this SPA navigation is about 20 or so lines of JS. Everything else is CSS and WebSockets. The state management is almost as simple.
* You have a large number of users compared to your resources and you can’t afford for your user base to always hit your server. Comparatively, deploying API-only apps is far cheaper when you’re resource-starved (eg early stage startup).
* You don’t care about SEO, for example you’re building internal tooling. You then don’t need to care about hydration at all. Much simpler to separate concerns (again esp at the beginning).
* Offline mode (eg PWA or reusable code in Electron) or cases where you want to be resilient to network failures. In the case that your app is dependent on the server for basic functionality like navigation, you can’t support any type of offline mode.
No, you found some tradeoffs and decided that the drawbacks are worse than the advantages. If industry disagrees, they tend to have their reasons, but as we love being tortured artists and really feeling our individualism, offbeat hot takes are always in demand.
That's all I see in quite a few HN titles ;D
Especially if they have some kind of AI integration feature.
He is _not_ talking about a SaaS dashboard SPA. He's talking about marketing sites and other content heavy stuff like blogs, landing pages, etc. It mentions this in many places if you go past the headline.
He is completely correct. SPAs should not be used for marketing sites full stop. Perhaps there are some edge cases where it may make sense (though I cannot think of any) but in general, if you are building anything that resembles a blog or landing page with nextjs et al you have done it wrong, close the code editor and start again. I'll give you a pass if you are developing an MVP of something and you need something up very quickly, but if you have any commercial traffic you will thank my later.
I have done a lot of audit work for this kind of stuff. Things I've seen:
10MB+ of React/JS libs to load a simple blog page
Putting images in the bundle, base64d. So badly that the page crashes OOM on many devices.
And my favourite of all time - shipping 120MB (!) of JSON down for a catalog. It literally loaded _the entire database_ to the front end to show _one_ product. It wasn't even an ecommerce site; it was literally a brochure of products you could browse for.
I can't relate to the situations, problems, or solutions this article seems to just take for granted.
Now, I understand the argument that simple article-based websites shouldn't necessarily be SPAs. Page transitions are perfectly doable in pure HTML and CSS. But if you have less then trivial local state and complex + specific components, forcing the MPA pattern will only complicate your codebase.
I'm sure there exist (foolish) efforts to make CSS somehow able to do some UI logic, but that is never a good idea. CSS is a poorly made/overly complex spec that deserves to die. It's too late to make that argument unfortunately, but to want even more of CSS in the modern web stack is kinda lunatic.
Javascript is over-rated.
CSS > JS
"I am Jack's native declarative transition."
Here's my header component, and all its scoped CSS, and here are the 5 subcomponents that make it up, and all their individual scoped CSS.
Page transitions are 0.001% of the desire to go the SPA route.
Before the SPA, these were common issues. That’s why there were a gazillion Java server pages frameworks to solve them. You also have frameworks that tried to encode the UI state in some way. My favorite was Seaside, which used continuations to store the UI state.
The following article should probably be titled “It’s time for modern bloggers to kill the clickbait titles” and discuss the trade-offs of each architectural decision more balancedly.
Id argue all the grousing of spa is because people made websites as apps when they should have been websites instead.
Btw view transitions are pretty slick and require zero js to get snazzy transitions.
Edit: there are some significant limitations with view transitions around performance and a few other gochas I should mention when they are used with pure css. I still love em tho.
What? This guy wanted to show off how much he knew about CSS and decided the only way to do it was completely make stuff up about a hot-button topic in webdev.
Another person mixing up web apps with web sites.
We do need frameworks for web apps. Yes people were wrongly making websites using frameworks.
But I am busy building web apps and without frameworks it is not feasible to build one.
This was NOT the reason why.
SPAs are better because it offloads as much processing as possible to EDGE cpu's. The idle compute among all users aggregates to a massive amount so might as well use it and minimize html construction and routing on the server side.
If the vanilla web can't do this easily, then it's not a good solution to your need for a SPA.
> Build a site like a site. Use HTML. Use navigation. Use the platform.
Sure, but what about all the other problems that aren't solved by View Transitions? There's some truth to the fact that frameworks like Next.js has jumped the shark. But they're not solving the problems of _just_ the SPA.
They are mostly shitty
---
Interestingly, every landing page or website for recent AI apps have looked AMAZING. Designers and standard website developers are totally on point. It's just, crappy developers who can't create a rich experience on top of incredible design that's the issue. CSS is not going to fix what can't be fixed (some people are not supposed to be in this profession, but hey, it pays ... for another three or so years).
I spent weeks trying to get it to behave predictably and failed entirely.
Don’t use this api if you value your sanity it’s the worst api I’ve used in a browser.
Why not spell out CMO and SPA and a civilian such as myself will not have to toddle off and dig out a search engine?
If you are going to get all assertive and pissed off, please be inclusive too.