Octane: React's programming model compiled without a virtual DOM

blweiner1 pts1 comments

Octane — React's programming model, compiled<br>Search docs⌘/Ctrl K

React’s programming model, compiled.<br>The successor to Inferno, carrying its performance-first goal forward: React’s hooks, Suspense and actions, compiled ahead of time. No virtual DOM. No rules of hooks. No hand-maintained dependency arrays — the compiler works out what your code captures for you.

Get started

Differences from React

Counter.tsrxCopy<br>// Counter.tsrx — hooks next to output, no rules of hooks<br>import { useState, useEffect } from 'octane';

export function Counter(props) @{<br>const [count, setCount] = useState(0);

// A hook behind a condition is fine — slots are<br>// assigned by call site, not call order.<br>if (!props.paused) {<br>useEffect(() => {<br>console.log('count is now', count);<br>}); // the compiler infers [count]

button onClick={() => setCount(count + 1)}>{'Count: ' + count}button><br>LiveCount0paused// count is now 0

No dependency arrays and no rules of hooks. The compiler tracks what your effects, memos and callbacks actually use, and hooks can sit behind conditions or early returns.

Independent use() calls start together instead of suspending one at a time down the tree. Nested fetches warm up early, and streaming SSR sends each boundary as soon as it’s ready.

Templates compile to cloned nodes and direct DOM writes, and keyed @for lists move the fewest nodes possible. Plain .tsx still works, so you can adopt .tsrx one component at a time.

Hooks, memo, context, portals, transitions, actions, controlled forms and Suspense all behave the way you expect. Events are native, refs are just props, and 43 first-party bindings cover the libraries you already use.

11,500+test executions across the runtime, compiler, SSR and bindings, including compiler-mode reruns; the core suite has 3,900+ distinct cases. React-derived coverage is tracked case by case<br>rules of hooks — put them behind conditions or after an early return

43first-party ecosystem bindings for state, data, routing, UI, forms, charts, 3D, and more

Fast should be how your app feels. Not a new way you have to think.<br>Why would I move my app to Octane?<br>Octane components are the components you already write. They are plain functions with hooks, props, and context. If you know React, you know Octane. Your instincts about where state lives and how data flows carry over on day one.<br>You don’t have to rewrite your app to adopt it. Keep your existing TSX, move components to TSRX one at a time, and ship the whole way. Components keep their shape along the way, so AI agents can migrate an app too, without redesigning it around a new reactive model.

Why isn't Octane built on signals?<br>Signals are a good tool, and you can still use them in an Octane app when they fit. But a framework built on signals makes every app represent and read state the signals way. Octane keeps components as plain functions that read from top to bottom. The compiler does the extra work, so your code doesn’t have to.

The trade holds up. Signals still win the workloads built for them. Across the checked-in suites below, Octane keeps pace without asking you to rewire how you think.<br>See what TSRX adds →

The libraries you already use, ported.

The mistakes that fail quietly<br>Octane compiles ahead of time, so a misconfiguration usually degrades instead of erroring. Two copies of the runtime in one tree break hooks and context silently, because hook state is keyed per runtime instance. Plain tsc mis-handles every .tsrx file. A declare module '*.tsrx' shim turns your own components into any. octane doctor is 20 checks over exactly those.<br>pnpm add -D @octanejs/cli<br>octane initWire Octane into a project you already have.<br>octane doctor --fixFind the quiet breakage, then repair it.<br>octane add react-hook-formInstall the binding that ports it.<br>octane explain 3Decode a minified production error.<br>octane mcp addGive your coding agent the Octane tools.

CLI reference

octane doctor<br>dependencies<br>✖Single Octane runtime2 copies of octane are installed<br>✔Vite peer rangevite 8.1.5 satisfies ^8.0.16<br>typescript<br>✖JSX import sourcejsxImportSource is not set<br>⚠Typecheck scripttypecheck runs plain tsc<br>✖No wildcard .tsrx declarationdeclare module '*.tsrx' found in 1 file(s)<br>3 failing · 1 warning · 11 passing<br>`octane doctor --fix` can repair 2 findings.

Incrementally migrate. With OctaneCompat.<br>Already have a React 19 app? Drop compiled Octane islands into it with a single component. Events stay native and delegated, islands read your real React context with plain use(), and they render on the server and hydrate on the client. Migrate one component at a time — no rewrite, no big bang.<br>The one thing that doesn’t cross over: React Server Components. Everything else — hooks, Suspense, context, SSR — comes along.

Read the OctaneCompat guide →

App.tsxCopy<br>// App.tsx — your existing React 19 app<br>import { OctaneCompat } from 'octane/react';<br>import { Counter } from './islands/Counter.tsrx';

export function App() {<br>return (<br>div...

octane react hooks tsrx count components

Related Articles