Octane

CI status: alpha npm version License: MIT

Octane is a fast JavaScript UI framework, and the successor to [Inferno](https://github.com/infernojs/inferno). You write components with the React API you already know, and a compiler turns them into direct DOM code before they ship. No virtual DOM, no rules-of-hooks bookkeeping, and no dependency arrays to maintain by hand. Created by [Dominic Gannaway](https://github.com/trueadm), who also created Inferno and has worked on React, Lexical, Ripple, and Svelte. ```jsx import { useState } from 'octane'; export function Counter() @{ const [count, setCount] = useState(0); } ``` ## Why Octane **Your React knowledge transfers.** `useState`, `useEffect`, `memo`, context, portals, Suspense, transitions: same API, same mental model, checked case by case against a large behavioral suite. React-derived coverage is tracked in the generated [parity report](./docs/react-parity-coverage.md) rather than inferred from the size of the suite. **Standard JSX works, `.tsrx` gives you more.** Paste a component from the React docs into a `.tsx` file and it runs. Or author in `.tsrx`, the spiritual successor to JSX, and get template directives (`@if`, `@for`, `@switch`, `@try`) that compile to keyed fast paths, plus an `@{ … }` shorthand that puts setup next to the output. Mix both dialects in one app and import across the boundary. [TSRX for VS Code](https://marketplace.visualstudio.com/items?itemName=Ripple-TS.ripple-ts-vscode-plugin) adds syntax highlighting, diagnostics, navigation, and completions for `.tsrx` files. **Write the closure, not its dependency list.** Omit the array from `useEffect`, `useMemo`, `useCallback`, and friends, and the compiler derives it from what the closure actually captures, including stable setters, dispatchers, refs, and state getters. This is the no-bookkeeping DX people associate with signal frameworks, without leaving the hooks model. Explicit arrays still mean exactly what they mean in React. **No rules of hooks.** Hooks are tracked by call site, not call order, so a hook can live inside an `if` or after an early return. The one rule left is enforced for you: a hook in a plain JS loop is a compile error, because every iteration would share a single call-site slot. Use the keyed `@for` directive instead, where each item gets its own hook state. **The platform, not a reimplementation of it.** Real delegated DOM events, controlled form components on native events (React's `value`/`checked` semantics, with `onInput` per edit and native `onChange` on commit), and refs as plain props (`ref={cb}`, `ref={obj}`, even `ref={[a, b]}`). No synthetic layer second-guessing the browser. **No virtual DOM.** Components re-render like React, but a compiled render path and an LIS-based keyed reconciler keep the runtime overhead minimal. Octane is deliberately narrow where React has grown wide: no class components, no Server Components, no synthetic event system. Those are choices, not gaps, and they are written down in [Differences from React](https://octanejs.dev/docs/differences-from-react). ## Also in the box - **Editable state that follows its source.** `useLinkedState` resets or adjusts local state as soon as an input changes, with no effect and no state update during render. - **Promises in render are safe.** No `cache()` wrapper: creations feeding `use()` are memoized at their declarations, including local `.then` chains. Independent requests start together, one suspension per stratum, and descendant fetch trees prefetch while an ancestor is still suspended. - **Streaming SSR and byte-stable hydration**, with out-of-order Suspense flushing over Node or web streams, or buffered and static rendering when you want it. - **Deferred hydration.** `` keeps server HTML visible but inert until it is worth activating, and splits its children into their own chunk by default. - **`class` / `className` composes clsx-style** everywhere: strings, arrays, objects, and nesting, at every apply site. - **A current-state getter.** `useState` and `useReducer` return `[state, update, getState]`, so a delayed callback can read the latest value instead of a stale capture. ## Install Octane's published packages need Node.js 22 or newer. Scaffold a project that already runs: ```bash npm create octane my-app cd my-app npm run dev ``` `--template spa` is a client-only app and `--template fullstack` adds routing, streaming SSR, hydration, and a production build; leave the flag off and it asks. In a project you already have, let the CLI wire it up instead, including the TypeScript settings `.tsrx` needs: ```bash pnpm dlx @octanejs/cli init ``` Or do it by hand: ```bash pnpm add octane @octanejs/vite-plugin ``` ```ts // vite.config.ts import { defineConfig } from 'vite'; import { octane } from '@octanejs/vite-plugin'; export default defineConfig({ plugins: [octane()], }); ``` ```ts // main.ts import { createRoot } from 'octane'; import { App } from './App.tsrx'; const root = createRoot(document.getElementById('root')!); root.render(App, { title: 'Hello world!' }); ``` Rspack and Rsbuild are supported too. [Getting started](./docs/getting-started.md) covers all three build tools, server rendering, hydration, streaming, deferred hydration, and profiling. ## Status Octane is in alpha. The runtime, compiler, and SSR/hydration paths all work, but APIs still move. The core suite contains **3,900+ distinct behavioral tests** across conformance, differential, hydration, runtime, compiler, and SSR coverage. The `octane-prod` project reruns the normal suite against the production compiler path, which is valuable mode coverage but is not counted again as unique tests. This is an Octane suite count, not a claim that every test was ported from React; the pinned snapshot and source-attributed React counts live in the [coverage ledger and report](./docs/react-parity-coverage.md). ## Documentation The full docs live at **[octanejs.dev](https://octanejs.dev)**, a site built with Octane itself. Good places to start: - [Quick start](https://octanejs.dev/docs/quick-start): install, mount, and the `.tsrx` essentials. - [Build tools](https://octanejs.dev/docs/build-tools): Vite, Rspack, or Rsbuild for SPA compilation and full-stack SSR. - [TSRX vs TSX/JSX](https://octanejs.dev/docs/tsrx-vs-tsx): when to reach for each dialect and what TSRX unlocks. - [Differences from React](https://octanejs.dev/docs/differences-from-react): the deliberate divergences, and why everything else matching React is the point. - [Publishing libraries](https://octanejs.dev/docs/publishing-libraries): package all importable authored code so applications compile libraries against their own Octane runtime. - [Bindings](https://octanejs.dev/docs/bindings): the `@octanejs/*` ports of the React ecosystem. - [Framework integrations](https://octanejs.dev/docs/framework-integrations): use Octane with Astro, Docusaurus, or TanStack Start. In this repository: - [Getting started](./docs/getting-started.md): install, build tools, mount, SSR, streaming, deferred hydration, profiling. - [TSRX basics](./docs/tsrx-basics.md): components, hooks, control flow, class composition, text input events, strong mode. - [Server rendering](./docs/ssr.md) and [deferred hydration](./docs/deferred-hydration.md): the full references. - [Differences from React](./docs/differences-from-react.md): the divergence contract. - [Bindings status](./docs/bindings-status.md): what each `@octanejs/*` package ports, its upstream version, and its known divergences. ## Packages This is a pnpm monorepo. [`docs/packages.md`](./docs/packages.md) is the generated inventory; the shape of it is: - [`octane`](./packages/octane) is the runtime and the compiler together: rendering, the hook API, the server (SSR) and client (hydration) entry points, and the compiler itself, exposed at `octane/compiler` with bundler adapters at `octane/compiler/vite` and `octane/compiler/bundler`. - The app layer: [`@octanejs/app-core`](./packages/app-core) holds the bundler-neutral config, routing, SSR, hydration codegen, and production handler, and the [Vite](./packages/vite-plugin-octane), [Rspack](./packages/rspack-plugin-octane), and [Rsbuild](./packages/rsbuild-plugin-octane) integrations build on it. [`adapter-vercel`](./packages/adapter-vercel) and [`adapter-cloudflare`](./packages/adapter-cloudflare) deploy the output; [`@octanejs/tanstack-start`](./packages/tanstack-start) is the TanStack Start integration. - Tooling: [`@octanejs/cli`](./packages/cli) (`create`, `init`, `doctor`, `analyze`, `add`, `explain`, `mcp add`), [`create-octane`](./packages/create-octane), the `npm create octane` entry point onto `octane create`, and [`@octanejs/mcp-server`](./packages/octane-mcp-server), which exposes Octane docs and compile tooling to AI agents over MCP. - The `@octanejs/*` bindings, each an Octane port of a React library: state (zustand, jotai, valtio, mobx, redux, redux-toolkit, tanstack-store), data and routing (tanstack-query, apollo-client, tanstack-router, remix-router), UI (radix, base-ui, aria, shadcn, motion, dnd-kit, sonner, floating-ui, lucide), forms and content (hook-form, tanstack-form, lexical, tiptap, mdx, i18next), data-heavy screens (tanstack-table, tanstack-virtual, recharts, visx), 3D (three), Web3 (wagmi, rainbowkit), and more. Parity varies by package. Some are behaviorally complete, others are explicitly partial or alpha, and [`docs/bindings-status.md`](./docs/bindings-status.md) is the generated table of record: upstream version, supported surface, known divergences, SSR/hydration coverage, and when the evidence was last checked. ## Contributing Bug reports, regression tests, docs, bindings, and core fixes are all welcome. [CONTRIBUTING.md](./CONTRIBUTING.md) covers setup, where a change belongs, the test policy, the generated files, and how pull requests are labelled and landed. ```bash pnpm install pnpm test pnpm typecheck ``` ## License MIT