Skip to content

SSR Environment Variables

This guide explains SSR-related environment variables in Zova within the Cabloy monorepo.

Why SSR env configuration matters

SSR behavior often depends on environment variables that do not matter in exactly the same way for purely client-side execution.

Zova exposes SSR-related environment variables so the framework can configure key behaviors directly.

Representative configurable variables

Representative variables include:

  • SSR_PROFILE
  • SSR_COOKIE_THEMEDARK_DEFAULT
  • SSR_API_BASE_URL
  • SSR_PROD_PORT

These affect SSR profile selection, theme defaults, server-side API targeting, and SSR production port behavior. Response-cache defaults are resolved from the selected request-local profile; body-ready behavior is an opt-in of the selected layout module, not an environment or profile switch.

SSR profile

SSR_PROFILE is the standalone-flavor default for request-local SSR behavior:

  • public: the server renders without request-cookie credentials or cookie-backed theme resolution. Output must be anonymous-safe and may use public response caching.
  • session: the server may recover request-cookie session state for normal route admission and authorized rendering. The response is always Cache-Control: private, no-store.

For Vona-backed SSR, SSR_PROFILE supplies the flavor default. After the frontend route is resolved, route.meta.ssrProfile can override that default before serverEntry runs. The resolved profile controls request-cookie capability and related SSR behavior; locale-aware URL handling remains the existing route.meta.locale contract. A profile never grants authentication, site admission, or API authorization; requiresAuth and Vona guards remain responsible for those decisions.

Route authors should choose the profile from the rendering contract rather than from the presence or absence of a locale parameter. Use session when SSR genuinely needs cookie-backed state, protected admission, personalized first paint, or private data; use public for an explicit URL-locale or deliberately locale-neutral, cache-safe, hydration-equivalent public contract. This is not an authentication requirement: an anonymous route should set requiresAuth: false, and session still does not grant Passport, Site, role, or API authority.

The selected layout owns sidebar restoration. A layout that enables layout.sidebar.bodyReadyObserver queues a request-local hidden-body metadata entry during SSR, registers its readiness condition and restoration callback, and then injects the generic browser observer. The observer restores browser-local sidebar state after the relevant layout DOM exists and reveals the body before hydration. Admin enables this path; Web and Empty disable it. Therefore, a Web route using ssrProfile: 'session' remains private, no-store without gaining the Admin sidebar observer.

The selected layout also supplies its own desktop sidebar fallback and responsive breakpoint: the Admin layout defaults to open and the Web layout defaults to closed, and both currently use 1023px as their independently configured breakpoint. Browser-local sidebar preference can override that fallback. The selected layout passes its breakpoint to the SSR browser handoff; it is not profile-specific. SSR profile selection does not change a layout's sidebar behavior.

SSR response cache control

After Zova resolves the route profile, a session response immediately receives Cache-Control: private, no-store, before router guards or rendering can terminate it. A successfully rendered public route receives a response-cache header according to the route's locale metadata and any explicit meta.ssrProfileOptions.responseCache policy.

For a public route, the default policy is:

  • meta.locale: true: use the configured public profile cache policy;
  • missing or false meta.locale: use expires: 0, which emits Cache-Control: no-cache, no-store, must-revalidate.

The second case prevents a CDN from sharing HTML whose hydration-time locale may still come from a browser cookie while the URL does not identify the locale. A route-level meta.ssrProfileOptions.responseCache override remains authoritative, including false; use an explicit override only when the route's complete SSR HTML is safe to share for that URL.

Cabloy Basic uses different flavor defaults:

FlavorDefault profileSSR response header
Webpubliclocale-aware routes use public, max-age=600
Adminsessionprivate, no-store

A route can override the flavor profile through meta.ssrProfile and can define a public response-cache policy through meta.ssrProfileOptions.responseCache. For Cloudflare cache-rule alignment that preserves these origin headers, see Docker + Cloudflare Deployment.

Theme implications of SSR_PROFILE

SSR_PROFILE determines whether the server can use cookie-backed theme state for the current request.

  • session: the server can resolve theme state from request cookies during SSR.
  • public: server theme reads are not authoritative for the browser's final theme. Keep theme-sensitive rendering hydration-tolerant and use the established browser-finalization path.

Use the active edition and UI library to determine the adapter-level implementation. Cabloy Basic and Cabloy Start share the profile contract but do not necessarily use the same SSR theme handoff.

For the broader theme usage contract and edition-aware checklist, see Theme Guide. For the runtime/flavor selection model behind these env choices, see Environment and Config Guide.

Dynamic environment variables

The runtime also exposes environment variables that describe the current execution context, such as:

  • SSR
  • DEV
  • PROD
  • CLIENT
  • SERVER

These are important because SSR-aware code often needs to distinguish:

  • server versus client behavior
  • development versus production behavior
  • SSR mode versus non-SSR mode

Implementation checks for SSR environment-sensitive changes

When editing SSR-sensitive code, do not assume one execution environment.

It should explicitly consider whether the code path depends on:

  • server versus client execution
  • dev versus prod behavior
  • SSR-specific environment configuration

That is often the difference between code that “works locally once” and code that fits the actual Zova SSR model.

For the broader mode/appMode/flavor and env/config loading model, see Environment and Config Guide.

Released under the MIT License.