Skip to main content
Tech Stack & Architecture

SPA vs SSR: Choosing Between a Single-Page App, Server Rendering and the Next.js App Router

By Obaid Tariq, Founder & Lead Engineer · Published

The short answer

The SPA vs SSR choice is best made per page type, not per product. Pages that must be found in search or load fast for first-time visitors (marketing, pricing, docs, blog) should be static or server-rendered; pages behind a login (dashboards, settings, editors) can be client-rendered like a single-page application without any SEO cost. The Next.js App Router lets you mix both in one codebase, defaulting to Server Components and adding client-side interactivity where needed, which is why it is a sensible default for a SaaS that has both a public site and an app.

When should I choose a single-page application versus server-side rendering or the Next.js App Router?

Choose static generation or server-side rendering for public pages that need search visibility and a fast first load, and a single-page application pattern for authenticated, highly interactive screens where SEO does not matter. If your product has both, the Next.js App Router is a good fit because it renders Server Components by default and lets you mark only the interactive parts as Client Components. A pure SPA (for example, Vite and React with a separate API) is still a good choice for an app that lives entirely behind a login.

The terms, briefly

  • Single-page application (SPA): the Next.js documentation defines a strict SPA as one served by a single HTML file, where every route, transition and data fetch is handled by JavaScript in the browser and there are no full-page reloads.
  • Server-side rendering (SSR): HTML is generated on the server for each request, so the browser receives content before JavaScript runs.
  • Static generation (SSG) or prerendering: HTML is generated at build time (or regenerated periodically) and served from a CDN.
  • React Server Components: components that run only on the server. In the Next.js App Router, layouts and pages are Server Components by default, and you add "use client" to the files that need state, event handlers or browser APIs.

Decide by page type

Recommended rendering approach by page type in a typical SaaS
Page typeNeeds search traffic?Recommended renderingWhy
Marketing, pricing, landing pagesYesStatic (prerendered), revalidated when content changesFastest first load; full HTML for crawlers and link previews
Blog and documentationYesStatic generation, with incremental regeneration if content changes oftenContent is the same for every visitor and must be indexable
Public app pages (shared reports, public profiles, listings)OftenServer-rendered or static shell with streamed dynamic partsContent varies by URL and should still be indexable
Logged-in dashboardNoServer-rendered shell plus client components, or a client-rendered SPAPersonalised data; SEO irrelevant; interactivity matters
Rich editor, canvas, spreadsheet-like toolsNoClient-rendered (SPA-style), possibly loaded only in the browserState lives in the browser; server rendering adds little
Settings, billing, adminNoEither; server rendering simplifies data access and authorisationSimple forms benefit from Server Actions and less client code

SEO implications

Google can index JavaScript-rendered pages, but Google Search Central's JavaScript SEO basics guide explains that it processes them in three phases (crawling, rendering and indexing) and that pages may wait in a rendering queue, sometimes longer than a few seconds. The same guide still calls server-side rendering or pre-rendering a great idea, because it makes pages faster for users and crawlers and because not all bots run JavaScript. For a public page that you want found, shipping real HTML is the lower-risk option.

If you do build public pages as an SPA, Google's guide gives specific rules worth following:

  • Use real <a href> links and the History API for routing, not URL fragments, so Googlebot can discover your pages.
  • Be careful setting noindex with JavaScript; Google says that when it sees a noindex tag it may skip rendering, so removing it later in JavaScript may not work.
  • Avoid soft 404s: client-side routes that show a "not found" message but return HTTP 200. Google suggests redirecting to a URL that returns a real 404, or adding a noindex robots meta tag.
  • Make sure titles, descriptions and canonical tags are present in the rendered output.

For pages behind a login, none of this matters: search engines cannot see them anyway. That is the main reason a logged-in dashboard can be a pure SPA with no SEO penalty. For the performance side of the same decision, see our guide to Core Web Vitals for web and mobile apps.

What the Next.js App Router changes

The App Router blurs the old SPA-or-SSR split. According to the Next.js documentation, Server Components render into a compact RSC payload, which is used together with Client Components to prerender HTML; the browser shows that HTML first and then hydrates only the Client Components. On later navigations the RSC payload is prefetched, so moving between pages feels like an SPA. With Cache Components (on by default for new apps created with create-next-app, according to the Next.js caching docs), a route is prerendered into a static shell and the parts that depend on the request stream in behind <Suspense> boundaries. Next.js calls this Partial Prerendering.

The Next.js docs also say it fully supports building SPAs: you can start as a static export (output: "export") and add server features later. The trade-off is that a static export cannot use features that need a server, which the docs list as including cookies, rewrites, redirects, headers, Proxy, incremental regeneration, default image optimisation, Server Actions and dynamic routes without generateStaticParams().

Costs and complexity

Operational trade-offs between rendering approaches
ApproachHostingComplexityTypical pitfalls
Pure SPA + separate APIStatic files on a CDN plus an API serverTwo deployables, but each is simpleLarge JavaScript bundles; loading spinners; request waterfalls; SEO if any public pages
Static site (SSG)CDN only; cheapestLowRebuilds or revalidation needed when content changes
Server-rendered (SSR)Server or serverless functions on every requestMedium; caching becomes importantSlow pages if data fetching is slow; compute cost per request
Next.js App Router (mixed)Node.js server, container or a platform such as VercelMedium to high; server/client boundary to learnAccidentally marking large trees as client components; caching surprises; framework upgrades

In our experience the hidden cost of the App Router is the learning curve around the server/client boundary and caching rather than hosting bills. The hidden cost of a pure SPA is usually performance on first load and the effort of building a separate public site. Both are manageable if you decide deliberately.

A practical recommendation

  1. If you have a public marketing site and an app, use one Next.js App Router project: static pages for marketing and docs, Server Components for data-heavy app pages, and Client Components for interactive widgets.
  2. Keep "use client" at the leaves. The Next.js docs recommend adding it to the files that define interactive components rather than marking large parts of the UI as client code.
  3. For a heavy editor, load it as a client-only component inside the app and keep the surrounding pages server-rendered.
  4. If your product has no public pages and your team prefers it, a Vite and React SPA with a separate API is simpler and entirely reasonable.
  5. If marketing is run by non-developers in a CMS, consider a separate marketing site; see WordPress vs Next.js.

When a different approach makes sense

If you are migrating an existing SPA, you do not need a rewrite; the Next.js docs describe incremental migration paths from Create React App and Vite. If your team works in Rails, Laravel or Django, server-rendered HTML with a small amount of client-side JavaScript remains a productive pattern for many SaaS apps. Our SaaS tech stack decision guide covers those options. If you would like help structuring an App Router project, our Next.js development team does this work; for a small app, following the Next.js documentation's own guides is usually enough.

Frequently asked questions

Is a single-page application bad for SEO?

Not necessarily, but it adds risk. Google can render JavaScript, though pages may wait in a rendering queue and other bots may not run JavaScript at all, so Google's own guidance still recommends server-side rendering or pre-rendering for important public pages. Pages behind a login are not affected because search engines cannot see them.

Do I have to use the App Router for a new Next.js project?

The App Router is where current Next.js features such as Server Components and Cache Components are documented, so it is the sensible choice for new projects. The Pages Router still exists for existing apps, and Next.js documents an incremental migration path.

What is the difference between SSR and React Server Components?

Server-side rendering produces HTML on the server so the first view appears before JavaScript loads. React Server Components are components that run only on the server and never ship their code to the browser. In the Next.js App Router they work together: Server Components are rendered on the server and combined with Client Components to prerender HTML.

Can I host a Next.js app without Vercel?

Yes. The Next.js deployment documentation says it can run as a Node.js server or Docker container with all features supported, as a static export with limited features, or on other platforms through adapters.

Sources

  1. Google Search Central: Understand JavaScript SEO basics — Crawl, render and index phases; rendering queue; server-side or pre-rendering still recommended; History API and href links; noindex and soft 404 guidance. Accessed 19 October 2026.
  2. Next.js Docs: Server and Client Components — Server Components by default; when to use Client Components; RSC payload, prerendering and hydration; keeping use client at the leaves. Accessed 19 October 2026.
  3. Next.js Docs: Single-Page Applications — Definition of a strict SPA; Next.js support for SPAs; static export option; migration from Create React App and Vite. Accessed 19 October 2026.
  4. Next.js Docs: Static Exports — Features unsupported in static exports. Accessed 19 October 2026.
  5. Next.js Docs: Caching (Cache Components) — Cache Components enabled by default for new apps; static shell with Suspense streaming; Partial Prerendering. Accessed 19 October 2026.
  6. Next.js Docs: Deploying — Node.js server, Docker, static export and adapter deployment options. Accessed 19 October 2026.

Recommendations without a source are AI Dev Planner’s own engineering opinion. Platform features and prices change; check the linked pages for the current position. Found an error? See our corrections policy.

Planning the front end of a SaaS?

Tell us which pages are public and which sit behind a login, and we will suggest a rendering approach that keeps SEO, speed and complexity in balance.