Skip to content

Hybrid Config

This page collects the settings you typically need for @lentystyle/hybrid. The goal is to answer these questions without dropping into low-level APIs:

  • which file do I create
  • which fields do I configure
  • how do build and dev behave
  • what are the defaults
  • when do I stay config-driven, when do I drop to low-level guard control

Select your package manager for the install command:

Terminal window
pnpm add @lentystyle/hybrid
  1. Install @lentystyle/hybrid

  2. Create luis.config.mjs in the project root

  3. Define the hybrid block

  4. Run the build script


import { defineLuisConfig } from '@lentystyle/core/config'
export default defineLuisConfig({
hybrid: {
buildMode: 'initial',
sourceRoots: ['./public', './dist'],
luisOutputDir: './dist/_hybrid',
assetBaseUrl: '/_hybrid',
globalCssFileName: 'lentystyle-global.css',
defaultRuntimeOptions: '',
},
})

Build script:

{
"scripts": {
"build": "astro build && pnpm exec lentystyle-hybrid build"
}
}

Generic dev middleware example:

import { defineMiddleware } from 'astro:middleware'
import { createHybridProjectDevMiddleware } from '@lentystyle/hybrid'
const hybridDev = await createHybridProjectDevMiddleware()
export const onRequest = defineMiddleware((context, next) =>
hybridDev(context.request, () => next()),
)

If a field is omitted, the core defaults are:

FieldDefault
buildMode'initial'
htmlOutputDir'./dist'
assetBaseUrl''
globalCssFileName'lentystyle-global.css'
globalManifestFileName'lentystyle-global.manifest.json'
writeRouteCssArtifactsfalse
defaultRuntimeOptionsundefined
hybridOptionsundefined
rewrite'auto'
include[]
exclude[]

In practice:

  • without buildMode the default 'initial' mode runs: route HTML scanning, single CSS + single manifest, and generated global CSS links in source-bearing HTML files
  • without htmlOutputDir, hybrid reads route HTML from ./dist
  • without assetBaseUrl rewritten asset URLs get no extra prefix
  • without globalCssFileName the shared generated CSS is written as lentystyle-global.css
  • without globalManifestFileName the global manifest is written as lentystyle-global.manifest.json
  • without writeRouteCssArtifacts, route mode does not write per-route .css files
  • without defaultRuntimeOptions source-level data-luis values apply on their own

FieldWhat it doesWhen you need it
buildMode'initial' (default): route HTML scan with one CSS + manifest and generated CSS link injection. 'global': source-only compile, single CSS + manifest, plus generated CSS link injection when htmlOutputDir is explicit. 'route': per-route payloadsAlways; use explicit 'global' when route HTML output is not available
htmlOutputDirFramework build output folder containing route HTML filesOverride it when your output folder is not ./dist
sourceRootsRoots where .luis source discovery runsAlways
luisOutputDirDirectory for generated LentyStyle CSS, manifest, and payload artifactsAlways
assetBaseUrlAsset prefix inside rewritten HTMLIf you want a custom prefix instead of a flat URL
globalCssFileNameShared generated CSS file nameIf the default lentystyle-global.css name conflicts with your asset naming
globalManifestFileNameGlobal manifest JSON file nameIf the default lentystyle-global.manifest.json name conflicts
writeRouteCssArtifactsIn route mode, also write one route-scoped .css file per processed routeOnly for consumers that fetch route CSS assets directly
defaultRuntimeOptionsUser-visible runtime behavior merged into discovered .luis sourcesIf generated manifests should request debug, performance, map, lazy, or worker
hybridOptionsTerminal-visible hybrid compile and rewrite diagnosticsIf build/dev should print hybrid debug or performance logs without changing user runtime output
rewriteRewrite policy for source .luis tagsIf you want to control runtime-vs-static output
include / excludeWhich HTML or .luis candidates to processIf you want to process only part of the project

In build mode runHybridProjectBuild() or the CLI first loads the config:

  • buildMode: 'initial' (default): route HTML files are scanned, non-observed plus initially matched ?/?! observed rules are written to one global CSS file, non-matching observed rules stay in the runtime manifest, and source-bearing HTML files receive the generated global CSS link with observed-only source markers
  • buildMode: 'global': all .luis sources compiled against empty HTML, single globalCssFileName + single globalManifestFileName written under luisOutputDir; all observed rules stay in the runtime manifest. If htmlOutputDir is explicitly configured and exists, the generated global CSS link and observed-only source markers are also written into route HTML files
  • buildMode: 'route': route-aware HTML mode reads route HTML from htmlOutputDir and writes per-route payload artifacts under luisOutputDir
  • include and exclude filter which candidates are scanned
  • route-scoped CSS files are skipped unless writeRouteCssArtifacts: true

Built-in Guard Defaults and Override Point

Section titled “Built-in Guard Defaults and Override Point”

Hybrid guard behavior varies by the active flow.

FlowBuilt-in guard behavior
Global modepreset: 'trusted-build', allowedLocalRoots: sourceRoots
Initial mode and route-aware HTML modepreset: 'balanced', htmlMode: 'hybrid'
Manual compileHybridBundle({...})Your provided guardPolicy if any

Default config-driven flow:

import { runHybridProjectBuild } from '@lentystyle/hybrid'
await runHybridProjectBuild()

This call reads the hybrid block and chooses global, initial, or route behavior from buildMode.

Custom policy example:

import { compileHybridBundle } from '@lentystyle/hybrid/node'
await compileHybridBundle({
routeId: '/docs/',
html: '<html><head></head><body><div class="card"></div></body></html>',
guardPolicy: {
preset: 'strict',
htmlMode: 'hybrid',
allowedLocalRoots: ['D:/project/public/styles'],
allowedRemoteImportOrigins: ['https://cdn.example.com'],
},
sources: [
{
sourceId: '/styles/docs.luis',
source: '.card { color: #0f172a; }',
},
],
})

rewrite accepts these values:

  • 'auto'
  • 'always'
  • 'never'

Recommended default for daily use:

rewrite: 'auto'

In practice:

  • if a route does not need runtime, source .luis tags can be removed
  • generated CSS links stay in place
  • routes that need runtime can keep source tags

The order of sourceRoots matters.

Example:

sourceRoots: ['./public', './dist']

This order is generally safer because it prevents old dist output from winning over live public sources.

Typical consequences of wrong order:

  • your latest source change is invisible
  • old .luis content is resolved during dev
  • expected selectors do not appear in generated CSS

These two fields use the same token parser, but they affect different places.

defaultRuntimeOptions: 'performance', // user-visible runtime behavior
hybridOptions: 'debug,performance', // terminal-visible hybrid diagnostics

defaultRuntimeOptions is merged into every auto-discovered .luis source. The result goes into the generated manifest or payload and changes what the browser runtime may do.

hybridOptions is read by the hybrid build/dev process itself. It controls compile timing, warning, and rewrite-decision logs. It does not change generated runtime options.

Supported defaultRuntimeOptions tokens:

  • debug / !debug
  • performance / !performance
  • map / !map
  • lazy / !lazy
  • worker / !worker

For hybridOptions, the accepted shape is the same, but only these currently affect hybrid diagnostics:

  • performance: prints hybrid compile/evaluate timing logs
  • debug: prints hybrid compile warnings and rewrite-decision logs

Object form is also supported:

defaultRuntimeOptions: {
performance: true,
lazy: true,
worker: 'auto',
}

General recommendation:

  • user-facing runtime default: defaultRuntimeOptions: 'performance'
  • build/dev diagnostics: hybridOptions: 'debug,performance'
  • no defaults: omit the field or use ''

defaultRuntimeOptions is applied to auto-discovered sources. A source-level data-luis can still override this default per source.

Config:

hybrid: {
buildMode: 'initial',
htmlOutputDir: './dist',
sourceRoots: ['./public'],
luisOutputDir: './dist/_hybrid',
defaultRuntimeOptions: 'debug,performance',
}

HTML:

<link rel="stylesheet" href="/styles/docs.luis" data-luis="!debug,lazy">

Effective runtime options for this source:

{
debug: false,
performance: true,
map: false,
lazy: true,
worker: 'auto',
}