CSR — Client-Side Rendering
The browser, not the server, builds the page. Great for internal tools and admin dashboards; poor default for public sites.
CSR — Client-Side Rendering
In one line: The server sends a near-empty HTML shell; the browser downloads a JavaScript bundle that builds the entire UI.
CSR is what early React, Angular, and Vue apps did. The server's only job is to send the JavaScript bundle. The browser then runs that JavaScript, asks for data via API calls, and constructs every pixel of the UI itself. Fast and snappy after the initial load. Painfully slow during the initial load, especially on a 4G phone. Bad for SEO unless you patch it.
How CSR works
The server sends a near-empty HTML shell. The browser downloads JavaScript that then builds the entire UI.
Flow:
- User requests
/products/42. - Server sends:
<html><body><div id="app"></div><script src="bundle.js"></script></body></html>
- Browser downloads
bundle.js, executes it. - JS makes API calls (e.g.,
fetch('/api/products/42')), builds the DOM, attaches handlers.
Until step 4 completes, the user sees a blank white screen. Slow networks make this worse — large bundles can take seconds to download and parse on cellular.
Pros
- Snappy navigation after initial load — no full page reloads.
- Server is just an API — no rendering work, much simpler backend.
- Familiar mental model — it's basically a desktop app in the browser.
Cons
- Slow initial load — large JS bundle, blank screen until JS runs.
- Bad SEO — search engine crawlers may not execute JS (Googlebot does, but inconsistently; most others don't).
- Bad for low-end devices or slow networks — CSR shifts work to the user's phone.
- White flash on first paint — bad first impression.
When to use CSR
In 2026, pure CSR is considered a poor default for public-facing sites. The industry has largely moved to SSR + hydration for public apps and CSR only for internal tools.
CSR remains fine for:
| Site type | Why CSR works here |
|---|---|
| Internal tools | No SEO needed; users tolerate a few-second first load |
| Admin dashboards | Behind a login, no SEO, users use it daily so initial load amortizes |
| Highly interactive apps (Figma, Notion) | UI complexity makes per-request rendering wasteful |
| Apps behind authentication | Search engines can't see them anyway |
The tools
| Tool | Notes |
|---|---|
| Vite + React/Vue/Svelte | The modern CSR stack. Vite is the dominant build tool. |
| Create React App | Deprecated. Don't start new projects with it. |
| Angular | Defaults to CSR (with optional Angular Universal for SSR). |
| SolidJS + Vite | Fast-rising alternative; very small bundles. |
Visit a CSR site (e.g., an old Create React App project). In DevTools → Network → reload:
- HTML response arrives. Size: ~1 KB. Body: an empty
<div id="root">and a<script>tag. - JS bundle arrives. Size: 200–500 KB compressed. The browser parses and executes it (100–500ms on a fast machine, multiple seconds on a slow phone).
- API requests fire. Each one is 50–500ms.
- Once all data is back, React/Vue mounts the components and the page becomes visible.
Time-to-first-meaningful-paint: typically 2–5 seconds on cellular. Compare to SSR (200–500ms) or SSG (50–100ms).
A common misconception: people think SSR and CSR are mutually exclusive. They're not.
Modern frameworks (Next.js, Remix, SvelteKit) do SSR for the first page load (fast first paint, good SEO) and then CSR for subsequent navigations within the app (instant, no page reload). You get the best of both. This is why pure CSR has fallen out of favor for public apps — the alternatives give you everything CSR offered plus a faster first impression.
Common mistakes
- Picking pure CSR for a public marketing site in 2026. It was the default in 2017. It is not in 2026. Crawlers see a blank shell, link previews break on Slack/Twitter, and LCP on a 4G phone is awful. Default to a hybrid framework (Next.js, Remix, Astro) unless the app lives entirely behind a login.
- Assuming "Googlebot runs JS" means SEO is solved. Googlebot is one crawler. Bing, DuckDuckGo, Slack, Discord, Telegram, OpenGraph scrapers, AI training crawlers — most of them do not execute JavaScript at all. They see
<div id="root">and index nothing. - Letting the bundle grow unchecked. "Just one more library" pushes you from 200KB to 800KB without anyone noticing. Add a bundle-size budget (
source-map-explorer,bundle-visualizer) to CI so the next 100KB dependency has to be justified. - Ignoring the loading state. A CSR app shows nothing until JS loads, runs, calls APIs, and renders. Without a server-rendered shell or a skeleton, users see a multi-second blank page and assume the site is broken. At minimum, ship a meaningful HTML placeholder.
- Falling for "SSR vs CSR" as a binary. Modern hybrid frameworks do SSR on the first request and CSR for subsequent navigations within the app. You don't pick one — you get both. "Pure CSR" is a specific choice with specific trade-offs, not the only alternative to SSR.
Page checkpoint
Did CSR stick?
RequiredWhat's next
→ Continue to ISR, Streaming & PPR where we look at the hybrid strategies the industry invented to get the best of SSG, SSR, and CSR all at once.