Server-side rendering
On the ssr adapter, your code runs per request: the runtime executes your server routes, renders HTML, and returns a fully-rendered page. This is what a commerce storefront wants, because prices, stock, carts and account pages are all buyer-specific and none of them survive being baked at build time.
The trade is a real cold start and real work on every request. Both are manageable; neither is free.
Where the render happens
Your server-side code runs at the origin, in Germany — not at the points of presence. The four points of presence in front of it terminate TLS, filter the request, and cache what is cacheable, so a rendered response still reaches the reader from nearby. The render itself happens in one place.
That shapes how to think about latency. A catalog or price read from inside your render is a read inside the same region, not a round trip across the network — so fetching from the platform on the render path is cheap. Fetching from a third party is not.
Responses are compressed with Brotli or Gzip on the way out, whichever the client accepts, and assets your pages reference are served and cached at the edge.
Each request has a time limit, set per site, up to a maximum of 30 seconds. If you're near it, the fix is almost never a longer timeout — it's moving the slow call off the render path. See Request timeout.
Getting a site onto the ssr adapter
Normally you don't. The platform detects the adapter from what your build produced and remembers it on the site — see Frameworks.
Set it explicitly when detection is wrong, or when you want the build to fail loudly rather than quietly serve a static bundle:
revenexx sites update --site-id <SITE_ID> --adapter ssr
Or in Cockpit, under Experience Studio → Sites, in the site's build settings. Either way it applies from the next deployment, so create one afterwards.
ssr on a project whose build emits only static files fails the build. That is deliberate: a silent downgrade to static is far harder to debug later than a failed build now. If this happens, your framework needs its server adapter configured — see the table below.A theme declares its adapter in the manifest, which is why a scaffolded theme deploys as ssr with nothing configured:
{
"site": {
"framework": "nuxt",
"adapter": "ssr",
"buildCommand": "npm run build",
"outputDirectory": ".output"
}
}
Per-framework configuration
Eight of the fifteen supported frameworks can build for ssr. Most need their server adapter selected in your own project before the build emits something the runtime can execute:
| Framework | What to configure |
|---|---|
| Nuxt | Nothing. The default npm run build emits a server build. |
| TanStack Start | Nothing. SSR is on by default. |
| Next.js | Nothing for the default output mode. Set output: 'standalone' in next.config.js for smaller builds and faster cold starts. |
| Angular | src/server.ts must use the @angular/ssr/node package. |
| SvelteKit | Use @sveltejs/adapter-node in svelte.config.js. |
| Astro | Use the @astrojs/node adapter in astro.config.mjs. |
| Remix | entry.server.tsx must use the @remix-run/node package. |
| Analog | Set ssr: true on the analog plugin in vite.config.ts. |
The install command, build command and output directory that go with each are in Build configuration. Note that Next.js changes its output directory entirely between adapters, and Nuxt's static build uses a different command — those two catch people out.
What the runtime injects
A running site receives these without you setting anything, at build time and at run time:
| Variable | What it is |
|---|---|
REVENEXX_SITE_API_ENDPOINT | The API endpoint the site should call |
REVENEXX_SITE_API_KEY | A scoped API key issued to this site's runtime |
REVENEXX_SITE_ID | The site's ID |
REVENEXX_SITE_NAME | The site's name |
REVENEXX_SITE_DEPLOYMENT | ID of the running deployment |
REVENEXX_SITE_PROJECT_ID | The project the site belongs to |
REVENEXX_SITE_RUNTIME_NAME | Runtime name |
REVENEXX_SITE_RUNTIME_VERSION | Runtime version |
REVENEXX_SITE_CPUS | Runtime CPU specification |
REVENEXX_SITE_MEMORY | Runtime memory specification |
REVENEXX_SITE_API_KEY is a server-side value. Read it in your server routes and never expose it to the browser — see The BFF pattern.REVENEXX_SITE_DEPLOYMENT is the one worth surfacing in a health endpoint or a response header, so "is this the new build?" has an answer that doesn't require reading logs.
Your own variables, and the NUXT_* names a theme reads, are covered in Environment variables.
Debugging
- The build failed after declaring
ssr. The build emitted only static files. Configure your framework's server adapter — see the table above. console.logoutput has vanished. Server-side output goes to the site's logs, not to the browser console.- Requests time out. Something on the render path is slow. Render the shell server-side and fetch the buyer-specific parts after paint — see Catalog, cart and checkout.
- Pages are slow under load, not individually. Check the server specification; the smallest size is not right for a server-rendered storefront.
- A
401calling the platform from a server route. You're readingNUXT_REVENEXX_API_KEYwhere the platform injectedREVENEXX_SITE_API_KEY, or the reverse. Map one to the other explicitly.
Related
- Static — the other adapter, and when it's the right one
- Rendering — the two adapters side by side
- Environment variables — yours, the injected set, and build versus run time
- Compute specifications — sizing the machine that renders
- Logs — where server-side output goes
- The BFF pattern — keeping credentials off the client