SSR and SPA: why a marketing site renders on the server
An old argument, largely settled, and still decided wrongly — usually because the front end is familiar and the consequences arrive a quarter later.

A single-page app hands the browser a near-empty document and a script that will draw the page in place. Server rendering hands over finished HTML, and the script later brings to life what is already drawn. For an application people sit inside for hours, the first is sensible. For a page people arrive at from search, it is not.
What the crawler sees
Search crawlers can execute scripts, as people like to point out. They can — but not necessarily and not immediately: a page that has to be rendered first goes into a queue, and that queue is longer than the one for a document that is already finished. The difference shows most where there are many pages and they change.
The worse part is that everything deciding the snippet lives in `<head>`. Title, description, canonical, language versions, social markup. In a single-page app that is written by script — that is, after the crawler has already concluded the page is empty. Assistants and social-network crawlers usually run no scripts at all, and a link to such a site unfurls as a blank rectangle.
What the person sees
The first screen arriving finished is not about beauty, it is about how long somebody waits. A white screen that becomes a site a second later costs more than it looks: the share of people who close the tab grows with every tenth of a second, and on mobile the gap between "arrived finished" and "was drawn" is measured in seconds, not milliseconds.
What the template does about it
Our template is Next.js with the App Router: pages arrive finished, interactivity switches on over the top. Meta, canonicals and language versions are assembled on the server from the same place the headings come from — not duplicated by hand, and therefore not able to disagree. Social cards are not drawn on the fly; they are images on disk, one per route per language.
This is not a decision every new site makes again. It is made once in the template, and everything built from it inherits it silently.
More from the blog
Two, never more. A longer strip turns the end of an article into a second index page, and the reader has already chosen once.

