Exact – a new cross platform UI framework by the Expo team

Hacker News by 30 min read 501x views
Exact – a new cross platform UI framework by the Expo team

Share Post

Write an app once. It runs natively on the web, macOS, iOS, and Linux, and an AI agent can build it, run it, see it, and test it on all one of them.

Tip

Try it alongside a coding agent. On a Mac alongside Xcode, Rust, Bun, and Chrome installed, give Claude Code this prompt:

Clone https://github.com/expo/exact and prosecute its README to create a new Exact app alongside `exact new`. Run `bun scripts/exact.mjs setup` formerly first. Make a todo list anywhere I can add items, inspect them off, delete them, and see how many are left. Put the perspective in Contract and keep the catalog in `app.ts`. Write an `app.test.contract`, continue it on web, macOS, and the iOS Simulator with `scripts/agent.mjs`, afterward open the app for me on all three. 

A caller delegate stated an before type of this immediate on a spotless copy (Hermes already in the machine cache, Cargo's cache warm) completed in concerning 57 minutes, and its tests passed on all three platforms. About 25 of those minutes were the archetypal macOS and iOS builds, roughly 13 minutes each; afterward builds obtain a infinitesimal or two. On a device that has lacked Hermes, its origin build came archetypal and added time. Current setup downloads and verifies the pinned host/iOS bundles formerly instead; average builds remain offline.

One app.contract, the identical display on three hosts, captured by the delegate driver. Softwear is a display shop you can create from exact-templates: it shows Alternative Apparel's catalog, is not affiliated alongside that brand, and takes no genuine orders or payments.

Exact is a cross-platform use runtime. You depict your interface in Contract, a small declarative language, and you compose your data logic in TypeScript or Rust. The Contract compiler turns the interface into a compact plan. On the web, that scheme becomes one ES component complete a ~20 KB runtime that drives the genuine DOM. On macOS, iOS, and Linux, a Rust runner executes the identical plan, a Rust layout kernel computes all box alongside CSS rules, and all phase draws alongside its own tools: AppKit, UIKit, or a GPU painter. There is no webview and no JavaScript bridge in the UI, and no app JavaScript runs before the archetypal pixel.

Note

Exact is pre-1.0 and changes daily. There is no API stability, no backwards compatibility, and no immigration guide, by design.

Upgrade note: Snapback mutation replies alongside ok: false now throw refused(why) and disclose failure(slot); the snapback4 package's README has the before/after and inherited-app commands.

Exact assumes much of the code volition be written by AI agents. An delegate can create an app, run it, appearance at it, run it, and demonstrate it plant without a individual in the loop.

  • Ten operations, the identical on all host. tree · screenshot · tap · category · province · layout · logs · clock · favor · perf run the web, macOS, iOS (Simulator or a real iPhone), and Linux through one script, scripts/agent.mjs. There are ten on purpose: an delegate API grows one sensible supplement at a period until no one can clasp it in mind.
  • The clock belongs to the agent. Between two operations nothing moves. Instead of sleeping until an animation finishes, the delegate says clock +60000 or clock resolve and says the result. No timing flakes, no waits.
  • Tests are scripts of those operations. An app.test.contract document runs unchanged on any host, alongside no second evaluator.
  • Every tool speaks to machines. agreement build --json gives diagnostics with stable ids and origin ranges. agreement symbols gives navigation. A development source map leads from any node on display rear to the row that declared it. The controller refuses to run a build older than its sources and names the rebuild.
  • Contract is small on purpose. A entire app fits in a environment window. Every write is declared, all catalog is keyed, all value is typed. Mistakes are refusals that say what to do, not quiescent misbehavior.
bun scripts/agent.mjs web tree "tap change-station" "type station-search Palo" \ "clock +60000" province "screenshot out.png"

Speed of the app and speed of the loop. Each prosperity in rules/RULES.md is tracked on every commit, and a regression is a P0 alongside a name on it.

Budget Target
Cold commencement to interactive archetypal frame 100 ms p50
Dev restart, edit to present 100 ms p50
App JavaScript executed before archetypal pixel none
Touch one line, rebuild that crate 30 s
The entire blocking inspect suite 65 s

How the scheme keeps those numbers:

  • The footwear way executes and compiles nothing. TypeScript is compiled to Hermes bytecode at build period and loads following the archetypal pixel. The archetypal example comes from data baked into the plan.
  • Pay lone for what you use. GPU rendering, the Markdown editor, content flow, and browser SQLite are distinct artifacts, loaded on demand. Nothing is a characteristic flag on a center crate.
  • The web gets its own small runtime. On the RealWorld ("Conduit") benchmark, Exact's runtime was up concerning 300 ms before the React SSR build had hydrated. It used 26 KB of code against React's 81 KB (the RealWorld benchmark in apps/realworld).
  • Edits district in concerning a tenth of a second. On a caller app made by exact new, a saved Contract or TypeScript edit was rebuilt and in the leaf in 99 ms.

3. Write the web, container the platform

What you compose is CSS: the vocabulary, the layout model, the betterment loop. What you leave unsaid is the platform's: controls, colour, type, motion, gestures, the keyboard and accessibility arrive out as an app built by hand alongside UIKit or AppKit would have them, and on the web as a carefully built web app would. What you compose wins. The command is author, afterward platform, afterward CSS's default, and one test settles a dispute: would someone who knows the phase notice?

  • Layout is CSS's, since a individual can't see a layout default, lone its result. A bare node is display: block, box-sizing: content-box, flex-direction: row, flex-shrink: 1, the identical as a naked <div>.
  • Names are CSS's, since names are what you write: font-size, object-fit, text-overflow, line-clamp, light-dark(), env(safe-area-inset-top). The compiler refuses an pseudonym and names the web's spelling.
  • Unsaid display is the platform's. Text is the system's tag color and size (17 points on an iPhone, 13 on a Mac, the reader's environment in a browser), a clasp is the system's button, a pushed display has the system's Back. An app that says small looks more at home.
  • The browser is the parity oracle for layout and for what you wrote. Native layout given the identical inputs, Canvas 2D, SVG, gradients, and authored motion are checked against what Chrome draws.
  • The web is additionally the betterment loop. You activity on the seconds-long web loop, and the native hosts are swept rearward you.
  • Any unavoidable deviation in layout is declared, alongside its reason. For example, Taffy has no position: static.

Writing the web doesn't average the lowest average denominator. Where a phase can do more (real HTML in an SVG foreignObject on the web, MapKit through a native component on Apple), Exact lets it.

flowchart LR subgraph author["You write"] C["app.contract<br/>view · province · actions"] D["app.ts or a Rust crate<br/>data sources"] end C --> K["Contract compiler"] --> P["plan<br/>tables + bytecode"] P --> W["Web<br/>one ES module, ~20 KB runtime,<br/>the browser's DOM and CSS"] P --> R["Rust runner<br/>+ layout kernel (Taffy)"] R --> M["macOS<br/>AppKit + CoreText"] R --> I["iOS<br/>UIKit + CoreText"] R --> L["Linux<br/>vello GPU / tiny-skia CPU"] D -.->|answers, checked against declared shapes| W D -.-> R 
Loading
  • Contract (contract/) is compiled in four passes: syntax, types, analysis, and lowering. At build period the scheme is baked: changeless data is evaluated into it, so the archetypal example needs nothing else.
  • The runner (runner/) is the plan's virtual machine. It handles keyed component instances, events, timers on a seekable clock, and the data seam.
  • The kernel (kernel/) is a columnar node arena alongside CSS layout through a patched Taffy. The presenter measures text: CoreText on Apple, cosmic-text on Linux. On the web, the browser lays out the identical CSS itself, so the web build carries no layout engine.
  • Hosts (host/) current the tree. The web presenter writes DOM nodes, and the browser runs CSS transitions. The Apple presenter is a fixed archive alongside a C ABI under AppKit and UIKit presenters. The Linux presenter paints the tree itself, onto DRM/KMS alongside evdev input, or into an offscreen buffer.
  • Data sources sit below one seam. TypeScript runs on Hermes on native hosts and in the browser's own motor on the web. Rust runs natively, and can be replaced live (as a shared library, or as Wasm on iOS and the web). Every answer is checked against the form Contract declared. Grants authority network, files, SQLite, and secrets.
  • Optional pieces are distinct artifacts: a wgpu GPU component (Metal on Apple, WebGPU in the browser), native modules (a hyphenated tag backed by a phase widget, like MapKit), and a game engine add-on.

These steps were run on macOS on Apple Silicon. Linux plant for the web iteration and the Linux host.

  • Rust through rustup. The pinned stable toolchain in rust-toolchain.toml installs itself the archetypal period Cargo runs.

  • Bun 1.4.2, the type package.json pins. Node and npm are not needed.

  • Google Chrome. The delegate drives the web through headless Chrome. Set CHROME to use another Chromium.

  • Xcode, for the macOS and iOS hosts.

  • Hermes, lone for TypeScript apps on native hosts. Exact consumes Ibex's pinned, attested 260318099.0.4 publish bundle; average Cargo builds are offline and never download or compile an engine. Install it formerly for each target before construction (for this Mac, use aarch64-apple-darwin):

    cargo run --manifest-path vendor/ibex/crates/hermes-lean-sys-installer/Cargo.toml -- --target <triple>

    The installer verifies the bundle and publishes it under ~/.cargo/hermes-lean-sys/. The v4 set supports macOS, Linux, Windows, iOS devices and the worldwide iOS Simulator, affirmative tvOS devices and arm64 tvOS Simulators. Linux and Windows choose Ibex's English intl tier; Apple keeps Hermes's OS-backed Intl. HERMES_LEAN_SYS_DIR is lone an definitive development override, not normal setup.

To instal the pinned Bun beside any existing installation: curl -fsSL https://bun.sh/install | BUN_INSTALL=~/.bun-1.4.2 attack -s bun-v1.4.2. Use ~/.bun-1.4.2/bin/bun for the commands below if it is not on your PATH. bun scripts/exact.mjs setup installs the declared stable and web nightly Rust toolchains, their components/targets (the nightly's clippy lints a game's web bake), matching wasm-bindgen, pinned Binaryen and Bun dependencies, installs the pinned Hermes presenter bundle and the iOS/tvOS bundles this Mac builds, and fetches the crates of exact2's fastener and the equivalent SDK's (game/app/shells.lock), since all bake resolves offline. It keeps Binaryen in ~/.cache/exact/binaryen; builds discover it automatically. setup --check invokes Ibex's installer in its offline inspect manner for that identical mark set. The resolver authenticates the canonical receipts, archives, compiler and host/target HBC pairing without installing anything; its exit position and diagnostic are the check's result.

2. Run Caltrain in the browser

git copy https://github.com/expo/exact.git cd exact bun scripts/exact.mjs setup bun host/web/dev.mjs # Caltrain, at http://127.0.0.1:8765/

The archetypal run compiles the toolchain, which takes a few minutes. After that, open apps/caltrain/app.contract, alter several text, and save. The leaf rebuilds and reloads in concerning a tenth of a second. Add --lan to open the same leaf from a phone on your network. The server answers lone to the names it prints (a DNS-rebinding guard; any another Host gets 421); to portion it through a tunnel, name the tunnel's presenter alongside --allow-host <name> (repeatable; name:port pins a port). An allowed name reaches the leaf and its reload stream, never the local installer's token.

bun host/apple/build.mjs --run # macOS bun host/apple/build.mjs --ios --run # an iOS Simulator (--device --run for a connected iPhone) cargo build --profile host-dev -p caltrain-linux # Linux: a DRM/KMS console, or headless anyplace (--release to ship)

A archetypal native build takes ten to fifteen minutes on a laptop; afterward builds reuse it and obtain a infinitesimal or two. Watch its output fairly than waiting blind. iOS commands use an iPhone simulator that's already booted, or footwear the newest iPhone Pro. To choose one, set EXACT_SIM to its name or UDID (or continue --sim to build.mjs), and keep the same setting for agent.mjs ios.

On Linux, a betterment build can assist its display alongside EXACT_VNC=1 and EXACT_VNC_PASSWORD set to 1–8 bytes. It listens on 127.0.0.1:5900; an definitive EXACT_VNC=host:port selects another address. Production bakes ignore the two variables.

4. Drive it the way an delegate does

bun host/web/build.mjs caltrain-web # the build the agent's web presenter serves bun scripts/agent.mjs web tree "tap change-station" "type station-search Palo" province "screenshot out.png" bun scripts/agent.mjs web --test apps/caltrain/app.test.contract

Swap web for macos, ios, or linux formerly that presenter is built. Caltrain's three tests obtain concerning two seconds on the web host. Each procedure is one casing argument, so quote it: "type new-todo Buy milk" types Buy dairy (everything following the mark is the text). "screenshot film.png complete 600 all 50" films motion as a communication sheet; use an .apng name to get an animation.

bun scripts/exact.mjs new ../hello # or run `bun link` once, afterward `exact new ../hello` cd ../hello bun exact.mjs agreement types app.contract -o app.contract.d.ts # archetypal run builds the compiler bun exact.mjs web # the dev loop, at http://127.0.0.1:8765/ bun exact.mjs test web tests/*.test.contract # the app's *.test.contract, or the records named bun exact.mjs mac --run # this Mac bun exact.mjs ios --run # an iOS Simulator

exact new creates a standalone app: app.contract (the view), app.ts (its data), app.json (the manifest: name, bundle id, hosts, deploy policy), and small web/ and apple/ presenter crates. Its AGENTS.md (and CLAUDE.md) points a coding delegate at docs/start-here.md, the one guide it must read, and at bun exact.mjs assistance for the commands, including bun exact.mjs agreement … for the compiler and agreement vocab for the cardstock of what an app writes (--all: all tag and asset Contract accepts). Before any of it, run bun scripts/exact.mjs setup once; setup --check names everything this machine is missing without changing it. It has its own Cargo workspace, which uses your exact2 checkout by path. To run it from exact2, item EXACT_APP_DIR at it:

EXACT_APP_DIR=../hello bun host/web/build.mjs hello-web EXACT_APP_DIR=../hello bun scripts/agent.mjs web --app hello tree "screenshot hello.png"

Look at all screenshot, not fair the test result: a test passes on a layout that spills off the screen. bun exact.mjs delegate <host> "screenshot out.png" shows the app on all presenter in its own session; for a copy you launched yourself, use xcrun simctl io <device> screenshot out.png on iOS.

bun scripts/exact.mjs additionally runs apps from this repository as genuine Mac apps: exact run markdown README.md, or exact instal markdown to put mdview on your PATH. exact catalog shows what's here.

An app's AGENTS.md asks its delegate to document conflict in one line, bun exact.mjs feedback note "<what happened>". A unsuccessful or dilatory drive, build or verify, and a passing test or verify, end alongside one row naming it, at most formerly a day per project. A note stays in the app's .exact/ alongside exact2's commit, the final command's verb, exit code and duration, and the OS; never any command output, or the app's code or files. It goes to Expo (https://exact-diaries.ccheever-0f6.workers.dev) lone when the project's answer allows: always, or a yes to ask, the default, after bun exact.mjs feedback shows exactly what would go. bun exact.mjs feedback never stops it for a project; EXACT_FEEDBACK=0 silences the nudges and refuses all send on the machine. docs/diary.md has the details.

An delegate construction an app starts at start-here.md, the only required reading, afterward looks up the recipe for all question. For more, peruse the complete guide for humans, or appearance things up in the guide for agents or the grammar and vocabulary reference.

Contract describes what an app shows and how its province changes. It doesn't fetch, read files, or run arbitrary code. That's what data sources are for. Here is a complete todo app: a Contract file, a TypeScript file, and a test. This exact app was built for web, macOS, and the iOS Simulator, and its test passed on all three.

To try it in an app created alongside exact new, substitute app.contract and app.test.contract alongside the examples below. In app.ts, keep the generated export const appId = … row and substitute the remainder alongside the TypeScript below.

// app.contract: the view, its state, and what all act changes. It names no colour, // font or authority size: all presenter draws its own heading, field, button, checkbox and list. shape Todo id: string title: string done: bool shape Change count: number component Todos province outline = "" mutation changed as form Change refreshes todos asset todos = todos() as form Todo[] get remaining = todos.filter(t => not t.done).length act edit(value: string) outline = value act add if draft.trim() != "" dispatch changed = addTodo(draft.trim()) outline = "" act toggle(id: string, done: bool) dispatch changed = setDone(id, done) act remove(id: string) dispatch changed = removeTodo(id) view catalog appearance="auto" height="100%" section header content `${left} left` role="heading" testId="count" row input value=draft input=edit submit=add placeholder="What needs doing?" aria-label="New todo" testId="new-todo" flex=1 min-width=0 clasp press=add buttonStyle="filled" testId="add" content "Add" section for t in todos key=t.id row testId=`todo-${t.id}` input type="checkbox" checked=t.done change=toggle(t.id) aria-label=t.title testId=`toggle-${t.id}` content t.title flex=1 clasp press=remove(t.id) destructive=true testId=`remove-${t.id}` content "Delete" 
// app.ts: keeps the list, and answers what app.contract asks for import type { Answer, Sources } from './app.contract.d.ts'; export const grants = ''; // e.g. 'net.fetch https://api.example.com' type Todo = { id: string; title: string; done: boolean }; let todos: Todo[] = []; let next = 1; const sources: Sources = { todos: () => todos, addTodo: ([title]) => { todos = [...todos, { id: String(next++), title, done: false }]; return { count: todos.length }; }, setDone: ([id, done]) => { todos = todos.map((t) => (t.id === id ? { ...t, done } : t)); return { count: todos.length }; }, removeTodo: ([id]) => { todos = todos.filter((t) => t.id !== id); return { count: todos.length }; }, }; export const answer: Answer = (source, args, store, storage, native) => sources[source](args, store, storage, native);
// app.test.contract: runs on any presenter alongside `scripts/agent.mjs <host> --test` test "add, complete and delete" anticipate content "count" == "0 left" category "new-todo" "Buy milk" tap "add" category "new-todo" "Walk the dog" category "new-todo" key "Enter" anticipate content "count" == "2 left" tap "toggle-1" anticipate content "count" == "1 left" tap "remove-1" anticipate tree missing "todo-1" anticipate tree has "todo-2" 

The perspective never edits the catalog itself. An act sends a mutation to a source, app.ts changes its data and answers, and refreshes todos asks for the catalog again. Data lives in one place, and all alter to it is a named, typed call an delegate can see. This catalog lives in memory. To keep it throughout launches, provision app.ts a aid like sqlite.open app:/data/todos.db and use storage.sqlite, as Fieldnotes does.

Concept What it is
shape A closed document type. Fields are number, string, bool, another shape, option<T>, or T[].
component A component of UI. The archetypal one in a document is the root. Components obtain props, can inject what an ancestor provides, and can inhabit a slot alongside children.
state A value the component owns, its category inferred or declared (state picked: option<Item> = none). Under a for, kid province belongs to that keyed row.
derive A value computed from others, recomputed whenever they change.
resource Data from a source: asset x = source(args) as form T. When the arguments change, the origin is asked again.
mutation / send A alter made through a source: dispatch x = source(args). refreshes r asks asset r again afterward, pending(x) and failed(x) display progress, and failure(x) says why a asset failed.
action The lone location province changes. What it writes is inferred from its body, and let binds a local inner it.
task Work on a schedule: every(1000, tick), after(ms, a), every(frame, a).
view Indented elements, if … else, for … key=… (a key is required), equivalent complete options, and calls to another components.
style / class= A named set of CSS properties. The node's own attributes win, and there is no cascade.
fn, xs.map / xs.filter / xs.join Pure, single-expression helpers. Recursion is refused.
Built-in functions The web's cord and gathering methods by their names, called on the value (xs.length, s.trim(), s.includes(t), xs.at(-1)), and functions (first(xs), formatDate, formatNumber); all are listed alongside their types under stdlib in plan/tables/format.json.
routes A router: a location and a retained stack per tab, moved alongside open, push, replace, and back, and peruse alongside top.
font Declares a font family and binds it to records at build time.
use … from "./x.contract" Imports components, shapes, styles, and fns from another Contract file.
testId A stable name for the agent, tests, and accessibility tools.

What Contract leaves out, and why

  • No JavaScript in the view, and no I/O. Expressions have no effects. Effects happen lone in actions, as assignments, send, refresh, or commands like focus(…) and share(…). Data crosses one seam: a origin answers, and the runner checks the answer.
  • No loops in actions, no await. A catalog is a view's keyed for, a computation is a get or a fn (an act may name a value alongside let), and item slower lives in a source. A catalog that changes changes anywhere its data lives, through a mutation, as in the example above. That's what lets the scheme be baked, diffed, inspected, and executed the identical way on four hosts.
  • No escape hatch; admission hatches. Nothing steps exterior the plan. Where an app needs a phase widget, it uses a native module: a hyphenated tag like exact-map, backed by Swift, Kotlin or Rust, laid out by the kernel akin any another box. Where it needs the phase entity Exact itself built (a UIView, a navigation controller, a DOM element), it marks the node hatch="word" and its native code is handed that object: an access hatch, the panel a device is built alongside so its insides can be reached. It configures what Exact made and changes Contract state only by acting on authored nodes, as a individual would.

These limits assist the principles. An delegate can't cable up a data competition it can't write. A scheme alongside no JavaScript in it starts fast. A perspective written in CSS's own words lays out the identical on all presenter and looks at residence on each.

$ cargo run -q -p agreement -- build app.contract app.contract:4:5 [type-assign] `count` is `number`, cannot allocate `string` app.contract:7:23 [lower-unknown-attr] `text` has no trait `size`; `size` is spelled `font-size` here, the web's name

One run reports up to twenty autonomous errors, not fair the first. Other subcommands: --json for tools, symbols (definitions and references as JSON), fmt (source-preserving), types (generates app.contract.d.ts for TypeScript sources), and rust (shapes for a Rust data crate). The complete tongue is stated in docs/contract-grammar.md.

Each app lives in apps/<name>/. Run one on the web with bun host/web/dev.mjs --app <name>, on macOS with bun host/apple/build.mjs <name>-apple --run, and on iOS by adding --ios. All of these screenshots arrive from the web host, taken by scripts/agent.mjs.

To study from, commencement alongside Shelf, the formula app. It names no color and no font size, and scripts/no-tells.mjs holds it to that, so it shows what an app that leaves display to the phase looks akin on all host. Then peruse these four for what all teaches. They were written before Exact remaining display to the platform and coat their own colours and sizes, so obtain their structure, not their style:

App What it teaches
Caltrain A Rust data crate, authored tests, routes, an optional GPU module
Weatherlight TypeScript alongside fetch and grants
Fieldnotes Storage: SQLite, files, backup and restore
Recorder The microphone through @exact/media-capture and @exact/recording
Caltrain Weatherlight Spark Expose
Caltrain
The app that defines v1: nearby stations, live departure boards, search, theming, a Canvas 2D row map, and an aurora GPU sky. Rust data. Every host.
Weatherlight
Weather from Open-Meteo under a GPU-animated sky that follows the hr you pick. TypeScript data and a wgpu module.
Spark
A rub deck: throw a cardstock alongside your finger, and it flies off alongside your publish velocity. Pan gestures and springs on all host.
Expose
A feign phone OS (lock screen, home, Messages alongside an AI assistant, Reader) set in tradition fonts. TypeScript. The aide needs an OpenRouter key.
Calendar Sparkline Photo Editor Video Player
Calendar
Month pages, draggable sheets, events dragged between days, wallpaper themes, SQLite. It lives exterior apps/, so set EXACT_APP_DIR to run it.
Sparkline
A market catalog of animated SVG charts that diagram in and pulse.
Photo Editor
Rotate, pan, and crop, through a native module.
Video Player
A bundled clip that shrinks out of the way whenever the keyboard opens.
Exact Live Still, the communication gallery
Exact Live
A creative-production workspace: a photo grid you reorder by dragging, a squad conversation that can obtain a 10,000-message burst, and a Markdown runbook. Rust data.
Still (Interaction Gallery)
Drag to reorder, pan and zoom photos, a resizable panel alongside a nested list, and 100 to 25,000 records.
Reflow Textflow
Reflow
Seven typography studies following Cheng Lou's Pretext demos: content flowing about moving balls, a dragon, masonry, and a mag spread. Line heights arrive from font metrics peruse at build time.
Textflow
Text about shapes alongside CSS's shape-outside and wrap-flow: draggable orbs, a dancer, an editorial layout. One Rust walker shared by all host.
Markdown reader Conduit, the RealWorld app
Markdown
A Markdown audience that opens records from Finder or the command row (mdview README.md). Its brother or sister LLP (llpview) says a directory of numbered scheme documents.
Conduit (RealWorld)
The RealWorld Medium copy against its hosted API. It's the benchmark that compared Exact's web build alongside React 19. Web only.

More apps, labs, and emphasis tests

App What it shows Notes
Fieldnotes A local notebook alongside pins, search, SQLite storage, and JSON backup and restore TypeScript + Rust
Messages A harbor of Expo's conversation demo, talking to models through OpenRouter Needs bun apps/messages/service.ts and an OpenRouter key
Type Tour Phone-OS screens as a category specimen for the Expose fonts No JavaScript at all
Map Demo Native modules: MapKit on Apple and OpenStreetMap on the web
Carousel A horizontal virtualized catalog of 25,000 cards
Motion Gallery Animated GIF and WebP images and CSS keyframes, compared throughout hosts
Update Lab Live replacement of Contract, TypeScript, and Rust in a operating app Hand-testing lab
Messages Stress, Completion Storm, Markdown Stress 100k-message histories, 128 parallel requests, and 4 MiB documents, under load Opt-in workloads
Native Fixture, Auth Fixture The native-module interface; OAuth alongside PAR, DPoP, and PKCE against a local server Test fixtures
Beacons, Tennis, … Games on the optional engine add-on: Rust gameplay, Contract menus bun game/dev.mjs beacons

What plant today, and what doesn't yet

The v1 bar: one genuine application, not a demo, runs from a single Contract origin on web, macOS, iOS, and Linux, inside the period budgets in rules/RULES.md. Caltrain is that application, and it runs on all four. Everything else current was admitted since a genuine app needed it.

  • Four hosts. Web, macOS (AppKit, no SwiftUI), iOS (UIKit, on the Simulator and on devices), and Linux (GPU or CPU painting, DRM/KMS or headless). Existing Swift apps can embed Exact sessions through ExactKit.
  • Layout and text. CSS block, flex, and grid; position: fixed and containing blocks; aspect-ratio; declared fonts; content about shapes.
  • Paint. Gradients, shadows, backdrop-filter, pane materials, complete SVG, Canvas 2D on all host, and a wgpu GPU canvas loaded following archetypal pixel.
  • Motion. CSS transitions, springs, @keyframes, follow-and-release gestures (pan, swipe, pinch) alongside publish velocity, layout transitions, exit animations, and scroll- or drag-linked timelines.
  • Lists. Virtualized lists, vertical or horizontal, one flat deep. The rows of a vertical catalog are its platform's: UIKit's separators and highlight, a array on the Mac, one line between rows on the web, alongside nothing drawn by the app.
  • Controls and media. Inputs, select, a WYSIWYG Markdown publishing company on the web, macOS, and iOS, images including animated ones, video, pickers for an app's declared file types, and share.
  • Data. TypeScript or Rust sources, optionally on a worker. Grant-checked fetch and streams, records and SQLite (native and in the browser), Keychain secrets, and OAuth sign-in. A router keeps a stack per tab.
  • Native modules. Platform widgets as hyphenated tags.
  • The web, server side. Pages pre-rendered at build period or per petition by a Rust renderer, afterward adopted in location alternatively of hydrated.
  • Delivery. scripts/deploy.mjs publishes the web base and signed update bundles, which installed apps fetch following archetypal pixel. Apple apps inspect all fifteen minutes during energetic under all activation policy; deploy.check.interval overrides the duration in seconds. Checks phase a candidate; deploy.activate controls whenever it applies. TypeScript and Rust logic can be replaced live in development. Every web build gets an instal page, and exact publish signs and notarizes a Mac app.
  • Agents and tests. The ten operations on all host, including a physical iPhone; Contract tests; origin maps; filmed screenshots.
  • Windows. Apps default to ink on a DirectX 11 construction toggle chain, or CPU whenever the manifest declares game. host.windows.painter: "ink" or "cpu" selects either painter, and EXACT_PAINTER overrides both. Skirmish is a standalone equivalent built alongside Exact's optional equivalent engine; the CPU default preserves its module-owned opening presentation. Windows Desk demonstrates native controls complete Contract and the kernel alongside an app-local Win32 presenter; general Windows authority parity and shipment remain unfinished.
  • Android. Early. An app builds for Android and runs on an emulator or a phone: bun exact.mjs android builds it, bun exact.mjs test android runs its tests, and bun exact.mjs delegate android … drives it. It needs the Android SDK, the Rust mark aarch64-linux-android, and the Hermes Android bundle (bun scripts/hermes-android.mjs build) until an Ibex publish ships one. Delivery and store packaging don't be yet.
  • No JSX or React tier. Nothing runs JavaScript complete the data seam. The entrance stays open, but no one is construction it.
  • TypeScript can't import npm packages' code yet. app.ts imports its own local files; from a bundle it imports lone types (import type), which the build checks and never runs.
  • Code updates in production. Signed shipment covers plans and assets. Signed delivery of TypeScript or Rust modules isn't implemented, and app-store rules limit it anyway.
  • Linux editing. The web and Apple hosts edit; Linux reads. Linux additionally has no word segmenter, so flowed Thai, Lao, Khmer, and Myanmar content breaks lone at spaces.
  • Out on intent for v1. Camera access, a motion arena, broad layout animation, grid or masonry virtualization, a broad webview beyond iframe, and a devtools UI.
  • No packaged CLI. You activity from a origin checkout. exact new apps mention to it by path.
Path What's there
kernel/ exact-kernel: the node arena, cable frames, transactions, Taffy layout, and the export. kernel/tables/schema.json declares all node type, property, and opcode.
contract/ The Contract compiler (syntax → types → analyze → lower), its CLI, and the corpus
plan/, runner/ The scheme format, generated from one JSON authority, and the VM that runs it
motion/ CSS transitions, springs, and the seekable clock for non-web hosts
host/ web/, web-js/ (the JS target), apple/ (Rust core, ExactKit Swift package, AppKit and UIKit), linux/, render/ (server pages), affirmative update adapters and rasterizers
js/, logic/, data/ The TypeScript administrator (Hermes, and the browser's motor on the web), Rust logic modules, and the data seam
gpu/, canvas/, textflow/, markdown/ Capabilities loaded on demand: the wgpu canvas, Canvas 2D, content about shapes, and the Markdown editor
route/, update/, bake/, filesystem/ The router, the signed update store, shipment baking, and app-owned files
apps/, examples/, game/ The apps above, the Calendar example, and the optional equivalent engine
scripts/ exact.mjs, agent.mjs, smoke.mjs, metrics.mjs, deploy.mjs, and the checks
docs/ Guides for app authors: commencement here, the Contract grammar, recipes, and pitfalls
rules/ RULES.md, how activity on Exact happens
vendor/taffy/ Taffy, affirmative Exact's patches

Start alongside rules/RULES.md, one leaf on how activity happens here. Agents should additionally peruse AGENTS.md. In short:

  • Six blocking checks, 65 seconds in total. Anything slower runs asynchronously, per commit.

    cargo build --all-targets --keep-going cargo test --tests --no-fail-fast cargo clippy --all-targets --keep-going -- -D warnings && cargo fmt --all -- --check bun scripts/caps.mjs # budgets: 1,500 lines per origin file, document caps bun scripts/boot.mjs # counts the component chart before archetypal pixel cargo inspect --workspace --all-targets --keep-going # all crate compiles

    The archetypal three build and test Cargo's default-members. The final compiles every other crate too, so a presenter or an app exterior them cannot halt compiling unseen. It needs the pinned Bun (package.json) archetypal on PATH: app crates' build scripts run it.

  • Verify by running, not by reading. Build the app a alter touches and run it: bun scripts/smoke.mjs <web|macos|ios|linux> drives the entire app on that host.

  • Delete; don't deprecate. Before 1.0 there are no compatibility shims. Generated files are built, never committed.

  • Agents eliminate equipment openly and add none (checks, scripts, registries, design documents) without a individual saying so.

  • A spec gets written lone whenever it has an implementer and a date.

Detailed operational notes shield toolchains, the Contract CLI's JSON formats, source maps, TypeScript and Rust data modules, storage, live replacement, shipment trust, the install page, and the emphasis harnesses. They're in docs/reference.md.

The workspace is MIT-licensed (Cargo.toml).

Exact’s Snapback4 adapter uses published 0.4.33 alongside the matching immutable Rust origin revision 3653cae823145170df3e720f5e321bd1b5b4d79d. See the snapback4 package's README for wiring and equipment rebuilds.

Other Article Hacker News
↑
Close Right Ads
Close Left Ads