Skip to content

SSR Overview

@lentystyle/ssr is the SSR orchestration layer that injects CSS and runtime payload into a route HTML snapshot. It does not render framework HTML itself; it consumes an existing HTML snapshot and the .luis source list for that route.

Compiler -> Hybrid -> SSR -> HTML Response

Terminal window
pnpm add @lentystyle/ssr

  • Takes a route HTML snapshot
  • Compiles the .luis source list for that route
  • Injects the generated CSS into the HTML
  • Writes the route payload as <script type="application/json">
  • Provides adapter seams for framework or server integration
  • Offers optional in-memory cache for repeated renders in the same process
  • Validates request HTML and source envelope inputs in strict mode with @lentystyle/core/guard/ssr
  • Does not render framework HTML for you
  • Does not start the browser runtime
  • Does not auto-discover route sources
  • Does not provide distributed cache or persistent storage

The SSR request flow uses @lentystyle/core/guard/ssr.

This adapter:

  • uses the strict preset by default
  • enforces htmlMode: 'ssr'
  • keeps the LentyStyle SSR payload and bootstrap allowlist strictly SSR-only
  • blocks invalid request HTML or source envelope inputs before hybrid compilation starts

In high-level SSR helpers you do not enable guard separately; it runs inside the request render flow.

import { renderLentySsrSnapshot } from '@lentystyle/ssr'
await renderLentySsrSnapshot({}, {
routeId: '/docs/',
html: '<html><head></head><body><div class="card"></div></body></html>',
sources: [
{
sourceId: 'docs.luis',
source: '.card { color: #0f172a; }',
},
],
})

The built-in behavior is fixed:

  • preset: 'strict'
  • htmlMode: 'ssr'

The public renderLentySsrSnapshot() and createLentySsrIntegration() surfaces do not directly accept guardPolicy. If custom validation is needed, you must run guard separately one layer above SSR or drop to lower-level orchestration.

import { scanSnapshotEnvelope } from '@lentystyle/core/guard/ssr'
const findings = scanSnapshotEnvelope(
{
routeId: '/docs/',
html: '<html><head></head><body><div class="card"></div></body></html>',
sources: [
{
sourceId: 'docs.luis',
source: '.card { color: #0f172a; }',
},
],
},
{ preset: 'strict', htmlMode: 'ssr' },
)
console.log(findings.length) // 0

  1. Generate the route HTML snapshot
  2. Prepare the .luis source list
  3. Choose the right SSR surface
  4. Write the result.html output to the response

Available surfaces:

  • renderLentySsrSnapshot() → one-time render
  • createLentySsrIntegration() → reusable direct surface
  • createLentySsrFrameworkAdapter() → framework seam
  • createLentySsrProd() → helper with process-local cache support

import { renderLentySsrSnapshot } from '@lentystyle/ssr'
const result = await renderLentySsrSnapshot(
{ mode: 'ssr' },
{
routeId: '/docs/',
html: '<html><head></head><body><div class="card"></div></body></html>',
sources: [
{
sourceId: 'site.luis',
source: '.card { color: red; }',
},
],
},
)

After the call:

  • result.css contains the generated CSS
  • result.runtimePayload contains the hybrid route payload
  • result.html contains the final injected HTML

Low-level SSR APIs are object-based and do not require luis.config.mjs. But in app-level preview and project helper flows it is more useful to keep common SSR settings in the same config file.

import { defineLuisConfig } from '@lentystyle/core'
export default defineLuisConfig({
ssr: {
mode: 'ssr',
outDirName: 'dist-ssr',
defaultRuntimeOptions: '',
include: ['**/*.html'],
},
})

SSR also keeps convenience and hardening roles separate:

  • the browser runtime stays optional and convenience-oriented on the client side
  • @lentystyle/core/guard/ssr hardens the incoming HTML snapshot and source envelope input on the server side

Thanks to this separation, SSR can stay strict about payload and bootstrap HTML while the browser runtime keeps its own standalone policy model.


  • Config for request-level and project-level settings
  • Browser Runtime for browser-side convenience behavior
  • @lentystyle/guard docs for the fail-closed validation model