@lentystyle/hybrid is the integration layer between the compiler and the runtime. It does not replace either one; it coordinates generated CSS, manifest or payload artifacts, and optional HTML rewrite flow on the Node side.
Compiler -> Hybrid -> RuntimeWhat Hybrid Does
Section titled “What Hybrid Does”- Compiles
.luissources in global, initial, or route-aware mode - Produces shared generated CSS plus a global manifest or route runtime payload files
- Runs static-site build and dev integration
- Provides browser payload dispatch and rescan helpers
- Provides generic factories for framework adapters
- Validates source and HTML envelope inputs with
@lentystyle/core/guard/hybridbefore compilation starts
Guard Profile
Section titled “Guard Profile”Hybrid runs @lentystyle/core/guard/hybrid before compilation.
In HTML-based flows this adapter:
- uses the
balancedpreset by default - enforces
htmlMode: 'hybrid' - keeps framework dev scripts outside the SSR-only script allowlist
- can stop invalid route HTML or source envelope inputs before compilation starts
Default guard flow
Section titled “Default guard flow”In config-driven build and dev flows you do not enable guard separately; hybrid calls it for you.
import { runHybridProjectBuild } from '@lentystyle/hybrid'
await runHybridProjectBuild()The built-in policy depends on the active build mode:
global:preset: 'trusted-build',allowedLocalRoots: sourceRootsinitialand route-aware HTML:preset: 'balanced',htmlMode: 'hybrid'
When custom guard settings are needed
Section titled “When custom guard settings are needed”The hybrid block in luis.config.mjs currently does not expose a guardPolicy field. If a custom policy is needed, you need to drop down to the low-level compileHybridBundle() API.
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; }', }, ],})This path is for situations where you want stricter or looser validation while keeping low-level hybrid compile behavior.
Recommended Starting Point
Section titled “Recommended Starting Point”The recommended path for Node-based projects is a config file and a single build command.
- Install
@lentystyle/hybrid - Create
luis.config.mjsin the project root - Define
buildMode,sourceRoots,luisOutputDir, and related settings - Add the
lentystyle-hybrid buildscript - Reuse the same config on the dev middleware or Vite plugin side
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: 'debug,performance', },}){ "scripts": { "build": "astro build && pnpm exec lentystyle-hybrid build" }}Build and Dev Flow
Section titled “Build and Dev Flow”The pnpm exec lentystyle-hybrid build command:
- reads
luis.config.mjs buildMode: 'initial'(default): scans route HTML, writes non-observed plus initially matched?/?!observed rules into one shared CSS file, links that generated CSS from source-bearing HTML files, and leaves non-matching observed rules to runtimebuildMode: 'global': compiles all.luissources against empty HTML, writes one shared CSS file and one global manifest, leaves all observed rules to runtime, and injects the generated CSS link whenhtmlOutputDiris explicitbuildMode: 'route': scans route HTML or source candidates, writes route payload artifacts and shared CSS- runs guard preflight before compilation
- writes route-scoped CSS files only when
writeRouteCssArtifacts: trueis configured (route mode only)
createHybridProjectDevMiddleware() or createHybridProjectDevIntegration():
- reuses the same config
- produces in-memory assets
- serves global or initial mode from one in-memory CSS + manifest
- rewrites HTML responses per route when
buildMode: 'route' - keeps guard preflight inside the dev flow
Vite projects can consume the same config via @lentystyle/hybrid/vite.
Build mode note
Section titled “Build mode note”buildMode: 'initial' (the default) scans route HTML and compiles each route against its actual first HTML snapshot. Non-observed rules and initially matched observed rules go into one shared CSS file; source-bearing HTML files receive that generated CSS link and their original .luis tags are marked as observed-only fallbacks. Observed rules that do not match the first snapshot stay in the runtime manifest.
buildMode: 'global' does not compile against route HTML. It compiles every .luis source against empty HTML and produces one shared CSS and one global manifest file. When htmlOutputDir is explicitly configured and exists, it also writes the generated CSS link and observed-only source markers into route HTML files for first paint. Without route HTML, it stays a source-only artifact build.
buildMode: 'route' enables the route-aware HTML scan. It reads route HTML from htmlOutputDir, which defaults to ./dist, and writes per-route payload artifacts.
Runtime and Guard Separation Inside Hybrid
Section titled “Runtime and Guard Separation Inside Hybrid”Hybrid deliberately keeps these two roles separate:
- the browser runtime still handles convenience-oriented payload application
@lentystyle/core/guard/hybridhardens the source and HTML envelope inputs before compilation starts
This is why a hybrid project can keep using browser runtime behavior after build, while the compile boundary stays fail-closed on the Node side.
Next Steps
Section titled “Next Steps”Configfor project settingsBrowser Runtimefor browser-side behavior@lentystyle/core/guard/hybridfor the fail-closed validation model