Sketchpad → TX-2 → Web

WEB ARCHITECTURE, CORRECTED.

In 1963, Ivan Sutherland drew on a phosphor display with the TX-2 light pen and built the first interactive ECS. TX-2 brings that architecture to the modern web: isomorphic logic, zero bloat, precise control.

LIVE SYSTEM // ECS
HYDRATIONReady
TICK / FPS
Signal Demo: awaiting hydration...
WHY TX-2

Fullstack ECS

Define components once. The same systems run on server and client with deterministic state and hydration.

Reactive Core

Signals, computed values, and effects without VDOM drift. Minimal allocations, maximal control.

SSR + Sync

Server-side rendering with hydration markers plus delta-compressed state synchronization.

Type-Safe RPC

Define procedures with runtime guards and TypeScript inference across the wire.

Performance Discipline

Query indexing, batched updates, and worker-ready schedulers for heavy scenes.

Zero Bloat

ESM-first, tree-shakeable modules. No framework runtime tax.

QUICK START
npm install tx2-ecs import { World, defineComponent, Component } from 'tx2-ecs'; import { h, Render } from 'tx2-ecs/client'; class Counter extends Component { private countSignal = this.defineReactive('count', 0); get count() { return this.countSignal.get(); } set count(value: number) { this.countSignal.set(value); } clone() { return new Counter({ count: this.countSignal.peek() }) as this; } } const world = new World(); const entity = world.createEntity(); world.addComponent(entity.id, new Counter({ count: 0 })); world.addComponent(entity.id, Render.create({ render: () => { const counter = world.getComponent<Counter>(entity.id, 'Counter')!; return h('div', null, h('p', null, `Count: ${counter.count}`), h('button', { onclick: () => counter.count++ }, 'Increment') ); } })); await world.init(); world.start();
DOCS MAP

Getting Started

Installation, project layout, build targets, hydration.

Read

Core Concepts

World, Entity, Component, System, Signals, Scheduling.

Read

Client / SSR

Rendering, hydration markers, event wiring, streaming.

Read

RPC & Sync

Type-safe RPC, rate limits, delta compression, auth hooks.

Read
DOCS // OVERVIEW

Architecture

TX-2 is an isomorphic ECS. Define components and systems once; run them on server and client. Hydration carries state across the wire without VDOM.

Entities & Components

  • Entity: ID-only container.
  • Component: State + reactive signals via defineReactive.
  • Systems: Functions over queries; phases: init/update/fixedUpdate/lateUpdate/cleanup.

Reactivity

Signals are first-class. Components expose signals; systems react via effects. No VDOM diffing; direct DOM ops in render system.

Rendering

Client: Render.create wraps a render() returning h() trees. Server: renderDocument(world) emits HTML + hydration markers.

RPC & Sync

RPC definitions live in server; clients call with inferred types. State sync uses delta compression; only dirty signals move.

Deployment

  • Bundle: npm run build (core/client/server + types).
  • Node SSR: import { renderDocument } from "tx2-ecs/server".
  • Client: include /dist/client/index.js or bundle with your app.
DOCS // CORE
// Define a component import { Component, defineComponent } from 'tx2-ecs'; class Position extends Component { x = this.defineReactive('x', 0); y = this.defineReactive('y', 0); clone() { return new Position({ x: this.x.peek(), y: this.y.peek() }) as this; } } export const PositionC = defineComponent('Position', () => Position); // System import { defineSystem, createSystemId } from 'tx2-ecs'; export const MoveSystem = defineSystem({ id: createSystemId('Move'), name: 'Move', phases: ['update'], }, ({ world, deltaTime }) => { const entities = world.query({ all: ['Position'] }); for (const entity of entities) { const pos = world.getComponent(entity, 'Position') as Position; pos.x.set(pos.x.get() + 10 * deltaTime); } }); // Wiring world.addComponent(entity.id, PositionC.create({ x: 0, y: 0 })); world.addSystem(MoveSystem); world.start();
DOCS // CLIENT & SSR

Client Render

Use Render.create to bind a render function. h(tag, props, ...children) builds DOM nodes directly; no VDOM diff.

SSR

renderDocument(world, opts) outputs HTML with hydration data. Include <script type="module" src="/dist/client/index.js">.

Hydration

hydrateWorld(world, { root, clearMarkers }) attaches to server markup and restores signals.

State Sync (server-driven)

Track dirty signals; ship deltas. RPC hooks can push state; clients patch into components.

EXAMPLES

Live Counter

Reactive signal demo running inside this page. Watch the HUD tick.

Open HUD

SSR Hydration

This page is server rendered via TX-2 and hydrated on load. No extra framework.

View Render

Particle Field

Pointer-reactive neon particle field driven by signals.

Run Demo
© 2025 TX-2 // Built with tx2-ecsSketchpad → TX-2 → Web