Frontend, with room to breathe.
weiv is a compiler-first frontend framework for single-file components,
direct DOM updates, and zero runtime by default.
- single-file components with clear template, script, and style boundaries
- TypeScript-friendly authoring without JSX
- plain local state by default
- explicit shared state only when it crosses component boundaries
- zero runtime by default; optional tiny runtime surface when needed
- direct DOM updates instead of a framework-wide VDOM layer
- runtime-level routing integrated with emitted component lifecycle
Runnable today, still pre-v1.
The current checkpoint includes a working direct-DOM browser path, compiler-driven invalidation, slot composition, shared observable runtime integration, runtime routing, and growing runtime/component verification.
The project is now beyond the initial experimental phase, but still needs:
- more precise dependency analysis
- broader app-scale verification
- diagnostics unification
- IDE/tooling polish
- additional runtime precision work
before it should be treated as production-ready.
Install the published package:
npm i -D weivjsThen run the included CLI:
npx weiv --help
npx weiv dev path/to/App.weivIf you want a static bundle instead of the dev server:
npx weiv compile path/to/App.weiv
cd ./dist
bun server.tscompile writes to dist by default. Pass an explicit output directory when
you want a different bundle location:
npx weiv compile path/to/App.weiv ./publicweivjs is now published with:
- CLI command:
weiv - bundler adapters:
weivjs/vite,weivjs/bun - optional typings:
weiv:observable,weiv:router
See packaging details in the NPM Single-Package Distribution docs.
For tooling and machine-readable failure handling:
npx weiv --json-diagnostics emit js path/to/App.weivThis emits canonical diagnostics JSON with:
actionsourcePathokdiagnostics(code,severity,stage,message,location,span,fatal)
The compiler is organized as a sequence of explicit representations:
parser -> SFC document + template AST
sema -> ScriptFacts + TemplateBindings
lower -> LIR
backend -> browser RenderTree + emitted artifacts
The parser owns the .weiv document shape: a single-file component has a
template section, a script section, and optional style section. Template syntax
is parsed into a template AST. Script and style stay as raw section text at this
layer so the document representation is complete without making parser own
TypeScript semantics.
Semantic analysis turns the raw script into ScriptFacts through the Rust FFI
script backend, then binds template references into TemplateBindings. The
lowering phase converts the target-neutral component information into LIR.
After that, ComponentUnit aggregates the phase outputs for one component.
Browser-specific work lives under the browser backend. It builds a RenderTree
from LIR, wraps browser-specific facts in BrowserComponent, and emits JavaScript,
scoped CSS, or a whole app bundle. App bundles additionally use an app graph to
collect component and runtime dependencies.
Useful compiler representations can be emitted directly:
npx weiv emit ast path/to/App.weiv
npx weiv emit sir path/to/App.weiv
npx weiv emit lir path/to/App.weiv
npx weiv emit render-tree path/to/App.weiv
npx weiv emit invalidation-graph path/to/App.weivEach of those writes to stdout by default. Add an output file to materialize it:
npx weiv emit lir path/to/App.weiv App.lir.txtPublic docs live at weiv.dev.
zig build test
zig build component-test
zig build runtime-test
zig build test-all
npm run test:package