Feels like React. Runs like vanilla JS.
A web framework for everything from static sites and SPAs to full-stack apps: TSX with scoped CSS built in,
signals, and 0 kB of JavaScript until a page needs it.
Website · Get started · Playground · Showcase · Benchmarks · MIT License
| 1.08× vanilla JS on js-framework-benchmark |
0 kB JavaScript on server-rendered pages |
6.4 kB runtime and app, compressed |
npm create lumiose@latest my-appPick a template (minimal, static, ssr or spa), then pnpm dev. Every new project starts agent-ready, with an
AGENTS.md and a Lumiose skill. Lumiose is pre-1.0, so APIs may still change between minor versions.
Most stacks make you assemble the pieces: a UI library, a styling solution, a meta-framework on top, and for content sites, a second UI framework for anything interactive.
Lumiose is one framework for all of it. You write components the way you already do in React, with their styles in the same file. Each route picks how it renders, from static HTML to a full SPA, and a page ships no JavaScript until it has something interactive. The compiler, written in Rust, turns components into direct DOM updates, with no virtual DOM.
import { signal } from "lumiose";
const accent = "#5546ff";
export default function Counter() {
const count = signal(0);
return (
<button class={{ pill: true, hot: count() > 9 }} onClick={() => count.update((n) => n + 1)}>
Clicked {count()} times
</button>
);
}
// One <style> block scoped to this file, with JS values like $accent.
<style>
.pill {
padding: 8px 16px;
border: 0;
border-radius: 999px;
background: $accent;
color: white;
}
.hot {
outline: 2px solid tomato;
}
</style>Counter runs once. Clicking updates only the text and the class that read count(). Try it in the
playground, which runs the compiler in your browser.
- TSX with scoped CSS.
.stsxfiles are JSX plus raw-CSS<style>blocks, scoped by where you put them, with JS values ($name) and build-time math. Stocktsctype-checks them, with no TypeScript plugins. - Signals, not re-renders.
signal,computed,effectandstoreupdate exactly the DOM nodes that use them. The rules of hooks, dependency arrays, stale closures and memoization go away. - Every rendering mode, per route. Static (prerendered HTML), server (streamed: the shell first, then each
<Suspense>boundary), islands (client:load,client:idle,client:visible) and SPA (client routing with a prerendered first paint). The same components work in all four. - The full stack, built in. File routes with layouts and a typed
href(), async components, form actions that work without JavaScript, endpoints, middleware, cookies, i18n, and a strict Content Security Policy with nonces. - Content as components. Import
.mdand.htmlfiles (GFM, front matter) as components, and any SVG, icon sets such as Lucide included, with?component(optimised and inlined). - Deploy anywhere. Node, Docker, Cloudflare Workers, Vercel, Netlify, Bun, Deno, Fly.io, Render, Railway, AWS Lambda or any static host, each with a deploy guide.
- Explicit, for you and your agent. Client boundaries are where you write them. Every diagnostic has a
LUMxxxxcode, a fix and a docs page. The docs ship inside the package (lumiose docs signals) and are served to agents over MCP. - Tooling included. The
lumioseCLI (dev, build, preview, check, lint, fmt), a language server and VS Code extension, oxlint/ESLint and Prettier plugins, and TanStack Query bindings in@lumiose/query.
| Stack | Full-stack layer | Styles | JS on a server page | Client speed | Server speed | |
|---|---|---|---|---|---|---|
| Lumiose | Built in | Built in | 0 kB | 1.08× | 619 renders/s | 1,323 req/s |
| React + Next.js | Separate project | Pick a library | 119 kB | 1.54× | 185 renders/s | 437 req/s |
| React Router | Built in | Pick a library | 101 kB | 1.54× | 185 renders/s | 683 req/s |
| Preact | None official | Pick a library | No full-stack layer | 1.52× | 208 renders/s | No full-stack layer |
| Astro (Preact islands) | Built in | Built in | 0 kB | 1.52× | 206 renders/s | 1,247 req/s |
| Svelte + SvelteKit | Separate project | Built in | 38 kB | 1.17× | 505 renders/s | 1,067 req/s |
| Vue + Nuxt | Separate project | Built in | 76 kB | 1.25× | 204 renders/s | 608 req/s |
| Solid + SolidStart | Separate project | Pick a library | 33 kB | 1.11× | 580 renders/s | 999 req/s |
| Remix 3 | Built in | Built in | 42 kB | 1.57× | 44 renders/s | 823 req/s |
JS on a server page: what the fullstack comparison's issue tracker loads for its home page, brotli (2026-10-12 · Apple M1 Max (10 cores) · macOS 27.0.1 · Node 26.8.1). Client speed: js-framework-benchmark's weighted factor, where 1.00 is the fastest framework in the run and vanilla JS scores 1.00. Server speed: renders per second of the SSR benchmark's 5,000-component page to an HTML string (2026-10-12, Node v26.8.1, Apple M1 Max (10 cores, 32 GB), darwin 27.0.0 arm64), then requests per second on the fullstack comparison's home page (2026-10-12 · Apple M1 Max (10 cores) · macOS 27.0.1 · Node 26.8.1). Both React rows use React's client and rendering entries. Rows after Lumiose are ordered by npm downloads of each stack's main package (2026-09-10 to 2026-10-09). Astro's interactive islands use a second UI framework: Preact in the fullstack comparison, so its client speed is Preact's. Solid islands would be faster on the client. Method and every run: benchmarks.
Not every project fits: When not to use Lumiose names the cases where another stack is the better choice today.
![]() |
![]() |
| Dotmatrix Pocket: a pocket chiptune studio (SPA, source) | Dotmatrix Advanced: a chiptune tracker (SPA, source) |
![]() |
![]() |
| Long Way Round: a travel journal (static + islands) | Bookshelf: a book catalogue (server) |
The website itself is a static Lumiose site, with islands for the search, the playground and the landing page's light.
The docs live in packages/lumiose/docs/ and ship with the package, so they always match
the installed version. Read them on the website, from the terminal
with lumiose docs, or through llms.txt. Good places to start:
Getting started,
Coming from React (or Next.js, React Router
and Solid) and
Rendering modes.
Lumiose is 0.x: any minor release may break the API, and breaking changes ship without migration paths until the first external production app or 1.0. The Stability page has the 1.0 criteria, what the API freeze covers, the supported Node.js versions and browsers, and who maintains Lumiose. Running it in production? Add your app to the Used by list. Security reports go through the security policy.
You need Node 24 or later, pnpm and Rust (rustup installs the toolchain in rust-toolchain.toml on first use).
git clone https://github.com/itsjavi/lumiose.git
cd lumiose
pnpm install
pnpm build:compiler # the Rust compiler, as a native Node addon
pnpm demo # pick an example, the website or a benchmark app and start itpnpm check runs what CI runs. CONTRIBUTING.md covers the demo runner, building the website, CI,
the compiler binaries and releases.
| Folder | What's in it |
|---|---|
packages/ |
The framework, the Vite plugin, the CLI, adapters and editor tooling |
crates/ |
The Rust compiler, with its CSS, SVG and content pipelines |
apps/web/ |
The website: landing page, docs, showcase, benchmarks and playground |
examples/ |
Example apps for every rendering mode |
benchmarks/ |
js-framework-benchmark, SSR and the fullstack comparison |
MIT. This covers the Lumiose packages, the website and all examples, except code vendored with its own notice: the Remix 3 benchmark entry (Apache-2.0).



