JA

CSR, SSR and SSG are about when the HTML gets assembled

Here is what this post covers:

There are three ways to build a web page

There are three answers to when and where a page’s HTML gets assembled. First, the acronyms.

AcronymStands forIn one line
CSRClient-Side Renderingthe browser assembles it
SSRServer-Side Renderingthe server assembles it, on every request
SSGStatic Site Generationit is assembled ahead of publishing

As a restaurant

SSG is a bento box made in advance. It is cooked and lined up before opening, so it comes out the moment you order. The catch is that everyone gets the same thing, and you cannot change the menu once you are open.

SSG. The HTML is assembled once from code and content before publishing and stored, and every request afterwards is served that finished file as-is Before publishing (once) Code and content Build Finished HTMLkept on disk published On every request (any number of times) Browser Server GET / returns the stored HTML as-is (no assembly)

SSR is a dish cooked to order. You can vary it per customer and always use the freshest ingredients. In exchange, the kitchen has to run before anything reaches the table.

SSR. Nothing is assembled at publishing time; on every request the server fetches data and assembles the HTML there and then Before publishing (once) nothing assembled yet published / first request On every request (starting here each time) Browser Server GET /topics server assembles the HTML here (fetch data, fill template) finished HTML

CSR is handing over an empty plate plus a bag of ingredients and a recipe, for you to cook at home. The restaurant (the server) only passes out an empty plate (empty HTML) and a bag (JS), so it travels light — but since you have to cook and plate it yourself once you get home (the browser runs the JS and assembles the HTML), it takes the longest before anything is edible.

CSR. The server returns only empty HTML and a JS file; the browser runs the JS, fetches data, assembles the HTML on the spot, and only then does the page appear Before publishing (once) only the code (JS files) is made ready to hand out published / first request On every request (starting here each time) Browser Server GET /rooms/xxx empty HTML + JS file browser runs the JS and gets ready to call the API GET /api/messages data (JSON) the browser assembles the HTML, and the page finally appears

This is where someone shows up to photograph the restaurant’s food (the HTML) — the crawler. A crawler is a program that search engines and social networks send around the web automatically. It reads what is on the page and uses it for search results and link previews.

The crawler did not come to eat, only to take a photo. And it will not wait around for the cooking to finish. So with CSR, the only thing it can photograph is the plate as handed over — still empty.

If the contents of the plate cannot be read, the page does not show up in Google or Yahoo results. Generally, the sooner a crawler can recognise what is on a page, the easier it is for that page to rank well.

The same crawler visiting the same server finds different things depending on the approach.

When a crawler visits the server, SSR and SSG let it find a plate with the finished dish on it, while CSR leaves it finding only an empty plate With SSR or SSGCrawlerServerPlatethe finished dish is on itcontents are readable→ can reach search results With CSRCrawlerServerPlateempty (empty HTML)contents not visible→ will not reach search results

One question settles the choice

Is this page the same for everyone, and known before publishing?

  • Yes → SSG (it can be made in advance)
  • No → SSR (it has to be made on the spot)

Pages that show a logged-in user’s name, or stock counts changing in real time, cannot be made in advance at all, so they land on SSR. Company pages and blog posts, on the other hand, look the same to everyone and only need rebuilding when they change, which suits SSG.

If neither can be made in advance, what decides between SSR and CSR?

That one question only gets you as far as the line between SSG and everything else. On the “no” side, SSR and CSR are close relatives, and telling them apart is the harder call. Both assemble on the spot; the only difference is whether that happens on the server or in the browser.

There are two things to weigh.

  1. Do you want search engines to see it? SSR returns finished HTML, so a crawler can read it straight away. CSR returns an empty plate, so as above, the crawler sees nothing. Pages you want in search results are SSR.
  2. Does the content keep moving after it opens? On screens like a chat or a dashboard, where the content keeps changing through an ongoing conversation with the server, HTML dutifully assembled by the server starts going stale the moment it renders. It makes more sense to do it all in the browser from the start and let the browser drive the updates too. That is CSR.

So the typical pairings are: wanted in search, static once open → SSR, and no need for search, keeps moving after it opens → CSR. Screens where the two do not line up — wanted in search but also constantly moving — do not settle neatly and remain the difficult cases.

A decision tree that first splits off SSG by whether the page is the same for everyone and known before publishing, then sorts the rest into SSR and CSR along two axes: whether you want search engines to see it, and whether the content keeps moving after it opens. The combinations where the two axes disagree converge on a single difficult case Same for everyone,known before publishing? SSG yes Want searchengines to see it? no Keeps movingafter it opens? yes Keeps movingafter it opens? no SSRthe typical case no CSRthe typical case yes Difficult caseSSR or CSR, needs thought yes no

How they divide up in a real project

These are the choices, screen by screen, in the anonymous chat service I am building as a side project.

ScreenPathChoiceWhy
Top page/SSGThe content lives in the code and looks the same to everyone. It is the entrance from search and ads, so I want it back as fast as possible
Service overview/aboutSSGSame as above
Topic selection/topicsSSRThe topic list can be changed from an admin screen. Making it in advance would keep serving a stale list
Matching queue/waitingSSRQueue status differs per person. There is nothing to make in advance
Chat room/rooms/{id}CSRConversation flows in real time. No need for it in search results either

What the table shows

All three are in use within one site. People say things like “this site is built with SSR”, but in practice each screen has its own fit, and mixing them is normal.

The more I want a screen in search, the more it leans towards being made in advance (SSG). It comes back faster, and the content is already complete by the time the crawler arrives.

Conversely, on screens that do not need to be in search, one positive reason to choose SSR disappears. The chat room is only seen by members, so there is no point having a search engine read it. That said, “does not need to be in search” on its own is fine with SSR too — it is not a reason to pick CSR. What decided the chat room was the second axis from the previous section: does the content keep moving after it opens? The conversation keeps flowing over WebSocket, so however carefully the server assembles the first HTML, it goes stale the moment it renders. Rather than lumping it together as “CSR is bad for SEO”, the real answer comes from both: do you want it in search, and does it keep moving after it opens?