The native-first framework for modern web apps.
A high-performance, zero-VDOM framework that compiles JSX to native DOM. Built with signals and standard Web Components.
How an update propagates
No virtual tree, no reconciliation pass. A change writes only to the DOM nodes bound to it.
Runtime performance
Our runtime against the React, Solid and Svelte 5 libraries. Median ms over 3 pooled runs, 4× throttled; lower is better.
| Operation | otfw | react | solid | svelte |
|---|---|---|---|---|
| create 1,000 rows | 261.1 | 274.1 | 244.3 | 257.6 |
| create 10,000 rows | 2627.8 | 3338.6 | 2542.2 | 2548.8 |
| append 1,000 to 1,000 | 295.8 | 286.1 | 270.1 | 267.4 |
| update every 10th (1k) | 91.8 | 93.8 | 108.9 | 92.5 |
| swap 2 rows (1k) | 33 | 246.4 | 31.1 | 31.3 |
| select row (1k) | 26.1 | 27.3 | 30 | 29 |
| remove row (1k) | 40.4 | 39.9 | 37.5 | 36.1 |
| clear 10,000 rows | 178.6 | 260.9 | 164 | 165.3 |
Bold beats the ~8.3 ms timing resolution; the rest are ties.
Build cost
Building a static site, not serving one — against Astro, Next.js, TanStack Start and Vite. Peak memory and wall time; lower is better.
| Metric | otfw | astro | next | tanstack | vite |
|---|---|---|---|---|---|
| Peak build memory (MB) | 140 | 416 | 1226 | 510 | 260 |
| Build time (s) | 0.3 | 1.2 | 3.8 | 2 | 0.8 |
The columns do not represent equal work.
Capabilities & roadmap
What ships today, and what is planned next.
Compiler-driven SPA engine.
Direct DOM operations, no diff.
$state, $derived, $effect, $context on fine-grained signals.
$ref to elements; imperative $expose.
Scoped DI with createContext, ContextProvider, and $context — no prop drilling.
Render a subtree into another DOM target; context resolves across the boundary.
Directory routing with client-side navigation.
Persistent UI across route changes.
Protect routes with custom logic + redirects.
Per-route lazy chunks in `otfw build`; dev compiles a route on first visit.
Preload route chunks on hover or when a link enters the viewport.
Pre-render routes to HTML at build time.
MDX pages and components; docs theme included.
Per-request HTML via otfw serve — the same render path as SSG.
First paint adopts the server DOM — pages, layouts, lists, conditionals, and islands with rich props.
App, Docs, or Library templates — JS/TS, auto-install, npm-pinned deps.
On-demand per-route compile. Edits under app/ rebuild and trigger a full-page refresh — not module-level HMR.
Hot-swap changed modules in place without reloading the tab.
In-browser error reporting during dev.
Component testing utilities.
Scaffold .tsx projects with tsconfig and macro typings; full editor tooling in progress.
Component, state, and network inspection.
Compiled by the toolchain — no extra config.
Component-scoped class names.
app/_middleware.js gates pages, API routes, loader data, and SSR — context.locals shared downstream.
getCookie / setCookie / deleteCookie on @opentf/web/server — RFC 6265 helpers for middleware, API routes, and loaders.
@opentf/web-form — porting to the new runtime.
File-based route.js / route.ts endpoints — standard Request/Response and dynamic params.
Route loaders (loader.js → router.data across SSR/SSG/SPA) + client-side resource(); queries and actions planned.
@opentf/web-i18n — URL-prefix locale routing, ICU messages, and Intl formatters (Phase 1).
ARIA helpers and a11y defaults.
Start building
Scaffold a project and follow the guides from an empty directory to a compiled app.