⌘K
L5E is an HTML-first SSR framework for block-builder MPAs. Pages without an island or useClientJs emit zero script tags. When you opt in, the framework tracks each call inside a per-request context and bundles only those assets — one CSS link, one script tag, sized to what actually rendered.
$ npm create l5e@alpha my-app -- --template basicStatic tooling can't see your runtime composition
Strategy A & B are what build-time tooling must choose between when a route's composition is dynamic. L5E watches what your render pass actually touched and bundles that — nothing more.
A page without an island, useClientJs, or swap+action emits zero <script> tags. No framework runtime, no hydration payload — just HTML.
useCss / useClientJs / island calls register into an AsyncLocalStorage context. Only rendered blocks contribute to the response.
When JS is needed, it ships as one bundled chunk. No inline blobs, no per-block tag spam, no waterfalls.
Render the whole page or fail clearly. No streaming, no half-rendered shells reaching the crawler.
Loaders set max-age, s-maxage, swr, and Cache-Tag. The CDN handles fan-out, not the framework.
Vanilla DOM, swap+action fragments, or React islands — pick the lightest hammer for the spot.
No bespoke routing DSL. Middleware, loaders, actions are first-class TypeScript you can read top-to-bottom.
L5E is alpha. Read the docs, try the basic template, file issues — feedback shapes v0.2.