This page explains the two separate config layers inside @lentystyle/ssr:
LentySsrConfigfor request-time rendering- the project-level
ssrblock insideluis.config.mjs
Minimal Setup
Section titled “Minimal Setup”pnpm add @lentystyle/ssrnpm install @lentystyle/ssryarn add @lentystyle/ssrTwo Separate Config Layers
Section titled “Two Separate Config Layers”LentySsrConfig is the public config type passed to renderLentySsrSnapshot(), createLentySsrIntegration(), and other request-time SSR surfaces.
This layer:
- defines runtime option defaults
- carries HTML injection metadata
- holds fields like
mode,adapter, andrewritePolicyin resolved form
LuisSsrProjectConfig is the ssr block inside luis.config.mjs.
This layer:
- holds shared app-level preview settings
- adds fields like
outDirName,include,exclude, andmaxEntries - is loaded via
loadLuisSsrProjectConfig()
LentySsrConfig
Section titled “LentySsrConfig”interface LentySsrConfig { mode?: 'static' | 'ssr' adapter?: 'none' | 'vue' | 'svelte' | 'react' | 'astro' performance?: boolean debug?: boolean map?: boolean lazy?: boolean worker?: 'auto' | 'main' | 'worker' assetBaseUrl?: string globalCssHref?: string bootstrapScriptSrc?: string runtimeOptions?: string | Partial<LentySsrRuntimeOptions> rewritePolicy?: 'auto' | 'prefer-static' | 'prefer-runtime'}Defaults
Section titled “Defaults”| Field | Default |
|---|---|
mode | 'ssr' |
adapter | 'none' |
debug | false |
performance | false |
map | false |
lazy | false |
worker | 'auto' |
assetBaseUrl | /_hybrid |
globalCssHref | null |
bootstrapScriptSrc | null |
rewritePolicy | 'auto' |
output.payloadMode | 'inline-json' |
Quick Example
Section titled “Quick Example”import { createLentySsrIntegration } from '@lentystyle/ssr'
const ssr = createLentySsrIntegration({ mode: 'ssr', globalCssHref: '/assets/site.css', bootstrapScriptSrc: '/assets/browser-entry.js', runtimeOptions: 'performance,!worker',})In this example:
- the common global CSS is injected as
<link rel="stylesheet">on every render - the bootstrap script is injected on every render
- the runtime options resolution gives
performance: trueandworker: 'main'
Built-in Guard Settings
Section titled “Built-in Guard Settings”SSR request helpers come with their own internal guard policy; you do not pass guardPolicy through config.
| Surface | Guard behavior |
|---|---|
renderLentySsrSnapshot() | preset: 'strict', htmlMode: 'ssr' |
createLentySsrIntegration().renderRequest() | preset: 'strict', htmlMode: 'ssr' |
createLentySsrFrameworkAdapter().render() | preset: 'strict', htmlMode: 'ssr' |
Short example:
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; }', }, ],})Even if you do not provide extra guard config, this call validates the request envelope and maintains strict validation in the downstream hybrid compile step.
Runtime Option Merge Order
Section titled “Runtime Option Merge Order”The runtime option merge order inside SSR is fixed:
package defaults-> config.debug / performance / map / lazy / worker-> config.runtimeOptions-> source.runtimeOptionsBase defaults are applied
{debug: false,performance: false,map: false,lazy: false,worker: 'auto',}Top-level config flags are applied
debug,performance,map,lazy, andworkerare applied at this stage.config.runtimeOptionspatch is appliedString or object patch overrides top-level flags.
Source-level override is applied
input.sources[].runtimeOptionsoverrides the config-level result per source.
String syntax
Section titled “String syntax”runtimeOptions: 'debug,performance,!worker'Result:
{ debug: true, performance: true, map: false, lazy: false, worker: 'main',}Supported tokens:
debug,performance,map,lazy!debug,!performance,!map,!lazyworker→worker: 'worker'!worker→worker: 'main'
Source-level override example
Section titled “Source-level override example”const result = await renderLentySsrSnapshot( { runtimeOptions: 'debug,worker' }, { routeId: '/docs/', html, sources: [ { sourceId: 'docs.luis', source, runtimeOptions: '!debug,lazy,!worker', }, ], },)Final runtime options for this source:
{ debug: false, performance: false, map: false, lazy: true, worker: 'main',}Request-level default and source-level override together
Section titled “Request-level default and source-level override together”Config:
const config = { runtimeOptions: 'debug,performance,worker',}Source:
const input = { routeId: '/docs/', html: '<html><head></head><body><div class="card"></div></body></html>', sources: [ { sourceId: 'docs.luis', source: '.card { color: #0f172a; }', runtimeOptions: '!debug,lazy,!worker', }, ],}Final runtime options for this source:
{ debug: false, performance: true, map: false, lazy: true, worker: 'main',}The ssr Block Inside luis.config.mjs
Section titled “The ssr Block Inside luis.config.mjs”The project-level SSR config type is LuisSsrProjectConfig. It inherits LentySsrConfig fields and adds preview or project-level fields.
import { defineLuisConfig } from '@lentystyle/core'
export default defineLuisConfig({ ssr: { mode: 'ssr', outDirName: 'dist-ssr', maxEntries: 100, defaultRuntimeOptions: '', include: ['docs/**', '**/*.html'], exclude: ['admin/**'], },})Additional project fields
Section titled “Additional project fields”| Field | Purpose | Default |
|---|---|---|
outDirName | Name of the preview HTML root directory | 'dist-ssr' |
maxEntries | App-level cache limit for prod helper | 100 |
defaultRuntimeOptions | Default runtime option string merged into project-level sources | '' |
include | Relative HTML path patterns to include | [] |
exclude | Relative HTML path patterns to skip | [] |
Project-level default example
Section titled “Project-level default example”import { defineLuisConfig } from '@lentystyle/core'
export default defineLuisConfig({ ssr: { mode: 'ssr', outDirName: 'dist-ssr', defaultRuntimeOptions: 'performance', include: ['docs/**'], },})In this setup defaultRuntimeOptions gives a common baseline to auto-discovered sources. If a source needs different behavior, override it with source-level runtimeOptions.
How to Load Project Config
Section titled “How to Load Project Config”loadLuisSsrProjectConfig(configOrPath?, overrides?)
Section titled “loadLuisSsrProjectConfig(configOrPath?, overrides?)”import { loadLuisSsrProjectConfig } from '@lentystyle/ssr'
const config = await loadLuisSsrProjectConfig(undefined, { cwd: appDir })This helper:
- loads the
luis.config.mjsfile - reads the
ssrblock - resolves request-level config fields
- applies project-level defaults like
outDirName,maxEntries,include, andexclude
Validation rules:
- throws if the config file does not export a real
ssrobject - if
includeandexcludeare provided, they must be string arrays outDirNamecannot be empty and cannot contain/or\
Normalized result
Section titled “Normalized result”{ configPath: '.../luis.config.mjs', configDir: '.../apps/site', outDirName: 'dist-ssr', outDir: '.../apps/site/dist-ssr', maxEntries: 100, defaultRuntimeOptions: '', include: [], exclude: [], runtimeOptions: { debug: false, performance: false, map: false, lazy: false, worker: 'auto', },}How include and exclude Work
Section titled “How include and exclude Work”shouldProcessLuisSsrProjectHtmlFile(htmlFilePath, config) converts the generated HTML path to a relative path under config.outDir and matches patterns.
import { loadLuisSsrProjectConfig, shouldProcessLuisSsrProjectHtmlFile,} from '@lentystyle/ssr'
const config = await loadLuisSsrProjectConfig(undefined, { cwd: appDir })
shouldProcessLuisSsrProjectHtmlFile( `${appDir}/dist-ssr/docs/index.html`, config,)Match rules:
- if
includeis empty, the file is included by default - if
includeis not empty, at least one pattern must match - then if
excludematches, the file is rejected
Example
Section titled “Example”ssr: { include: ['docs/**', 'blog/**'], exclude: ['blog/drafts/**'],}| Relative path | Decision |
|---|---|
docs/index.html | processed |
blog/post-1/index.html | processed |
blog/drafts/demo/index.html | skipped |
admin/index.html | skipped |
Supported mini-glob behavior:
***?
Path normalization always uses /.
Known Limits
Section titled “Known Limits”assetBaseUrl,mode,adapter, andrewritePolicyare carried in the resolved config; the current request-time SSR flow does not branch HTML behavior separately for each of themoutput.payloadModeis currently only'inline-json'defaultRuntimeOptionsis project-level metadata; the low-level render API does not read it directlyincludeandexcludeonly decide based on generated HTML relative paths; they do not do source discovery