# Server-Side Rendering

<EnterpriseFeature name="Dev Portal Server-Side Rendering" />

By default, the Zuplo-hosted Dev Portal is statically prerendered (SSG). Setting
`devPortal.serverSideRendering: true` in `zuplo.jsonc` builds and serves the
portal server-side for each deployment. Zudoku's
[protected routes](./zudoku/configuration/protected-routes.md) are enforced on
the server, so protected content leaves the public bundle and unauthenticated
requests cannot fetch it, as described in
[Server-side Content Protection](./zudoku/guides/server-side-content-protection.md).
**SSR applies to preview and production deployments only—never the working
copy.**

## Prerequisites

- The SSR enterprise add-on enabled on the account.
- The latest version of Zudoku. See [Updating the Dev Portal](./updating.mdx).
- For protected content,
  [authentication](./zudoku/configuration/authentication.md) configured and
  `protectedRoutes` set in the Zudoku configuration.
- The standard `zudoku build` build script in `docs/package.json`, which the
  scaffold includes by default. Zuplo appends the SSR build flags automatically.
  A custom build script that doesn't forward CLI arguments produces a static
  build instead.

## Enable SSR

Add the `devPortal` object alongside any existing settings in
[zuplo.jsonc](../programmable-api/zuplo-json.mdx) at the project root:

```jsonc
{
  "version": 1,
  // Other project settings...

  // Enable server-side rendering for the Dev Portal.
  "devPortal": {
    "serverSideRendering": true,
  },
}
```

No build-script changes are required. SSR takes effect on the next deployment.

### Example: protect partner documentation

Suppose partner documentation is available under `/partners/*` and should only
be available to signed-in users. With authentication already configured, add the
route pattern to `zudoku.config.ts`:

```typescript title="zudoku.config.ts"
{
  // ...
  protectedRoutes: ["/partners/*"],
}
```

Enable SSR in `zuplo.jsonc` as shown above, then deploy a branch. In the preview
environment, a signed-out request to `/partners/getting-started` shows the login
prompt instead of the page content. After signing in, the user can access the
page.

:::note

If the account doesn't have the SSR add-on, the deployment fails with an error
that directs you to contact support or remove the flag.

:::

## Test on a preview environment

:::caution{title="The working copy always uses static rendering"}

SSR takes effect on preview and production deployments only. The working copy
builds statically regardless of the flag, so protected routes are not enforced
server-side there.

:::

Deploy a branch to create a preview environment and validate SSR there. While
signed out, request a protected route and confirm that the login prompt appears
instead of the protected content.

## Caching

Responses to anonymous visitors are cached at the edge, so public pages stay
fast. Requests with a Dev Portal authentication session always render on demand
and are never cached.

## Reverting to static rendering

Remove `serverSideRendering` or set it to `false`, then redeploy. The portal
reverts to static prerendering, and the server infrastructure is torn down
automatically.

## Next steps

- [Configure protected routes](./zudoku/configuration/protected-routes.md)
- [Protect content server-side](./zudoku/guides/server-side-content-protection.md)
- [Configure authentication](./zudoku/configuration/authentication.md)
