Roadmap

What is shipped, and what comes next.

Shipped is what is on main. Next, Later and Exploring come only from what the repository records as planned or open: plans, not promises. This page follows the project's working record, .10x/status.md, and changes with it. Last updated 9 Oct 2026.

Shipped

In 1.0, 1.1 and 1.2

on main

What you can build on today, grouped. Each line has its page in the docs and its decision record in the repository.

No drift (1.2)

  • undra driftRecordings of one flow made on iOS, Android and the web, compared at the boundary: calls and their order, port answers, events, what was observed, the state each store ended in; --exit-code for CI.
  • Host ports under default main-actor isolation (ADR-066)A custom port compiles on iOS on the first try: a closure form beside the protocol, and a compile test under Swift's default main-actor isolation in CI.
  • Your own port, on three platformsA cookbook recipe whose Swift, Kotlin and TypeScript snippets compile in CI, with the registration line per platform.
  • The merge gate, measuredThe two longest Linux jobs split into halves that run side by side; the macOS splits measured no gain on a shared runner pool and were reverted; every job still runs on every change.

Bazel-first (1.1)

  • Bazel 8.8 and 9.x, testedBoth in CI, with the rulesets at their lowest and their newest versions.
  • Committed bindings, guarded (ADR-064)undra_bindings_test fails on drift and names the one command that updates.
  • The NDK as a declared input (ADR-065)No cargo-ndk anywhere; Android built in CI; the action is cacheable.
  • Lint exclusions by choiceBeside the trees, or none, for a repository that lints everything.
  • Symbol files and the debuggerundra symbolicate on a Bazel build; a breakpoint in a Rust frame from a rules_apple app.
  • A leaderboard of 100,000 rowsThe high-frequency recipe: ingest off the lock, publish a window, measured.
  • React Native 0.86Verified on the simulator and the emulator, the module unchanged.

Core and bindings

  • Records, enums and typed errorsFrom one schema, written as each language writes them.
  • Stores, signals and computedsReactive state in the core; one change-set per transaction.
  • Keyed and derived lists (ADR-039)A filtered view of 10,000 rows sends 158 bytes for one edit, not 353 KB.
  • Objects and host callbacks (ADR-040, ADR-041)Classes cross as themselves; the core calls back through typed interfaces.
  • Newtypes, Decimal, generic types (ADR-042)Read as native types on every platform.
  • Generic functions, objects and stores (ADR-058)Declared instantiations arrive as overloads and ordinary classes.
  • One error channel (ADR-032)Calls fail with a typed error; generated Swift never traps.
  • Several cores in one app (ADR-044)Each core is self-contained, storage included.

Platforms

  • SwiftUI, Compose and ReactPlus Vue, Svelte and Solid adapters for the web runtime.
  • React Native (ADR-038)A TurboModule over the C ABI under the same TypeScript mirror.
  • iOS 15 and 16 (ADR-045)ObservableObject stores below iOS 17; proven by compilation and a probe on iOS 26.5.
  • No manual build stepA Gradle task, an Xcode build phase and a Vite plugin run undra build.
  • Bazel rules (ADR-061)undra_core and undra_bindings, hermetic and offline; JVM, Node and Swift tested.
  • Everything from GitHub at one tag (ADR-063)The crates, the Swift package, the Kotlin modules (JitPack) and the npm runtimes; no account needed.

Data

  • Queries and mutationsStaleness, dedup, retry and optimistic updates with rollback.
  • Offline queue and persistenceQueued writes replay on reconnect and survive a restart.
  • Paged and lazy lists, polling (ADR-043)A lazy list pages 10,000 rows on demand; polling pauses with the app.
  • Migrations and typed storage (ADR-037, ADR-049)A changed schema still restores what the last version stored.
  • Snapshot, restore and web recoveryA crashed web core restarts from its last snapshot.

Ports

  • Ten ports, with adapters and fakesHttp, Kv, SecureStore, Fs, Clock, Rng, Log, Timer, Connectivity, Lifecycle.
  • WebSocket, SSE and Db (ADR-047, ADR-048)Streams with backpressure, and SQL over SQLite, each with a deterministic fake.
  • Your own network stack (ADR-060)OkHttp, URLSession and fetch as the app configured them.
  • Android adaptersBacked by the platform, installed with one call.

Dev loop and tooling

  • State-preserving reload (ADR-053, ADR-059)undra dev rebuilds on save and keeps the state and query handles.
  • Devtools (ADR-054)Live stores, a change-set timeline with time travel, port and query logs.
  • undra schema diff (ADR-062)Each API change marked breaking or additive, for review and CI.
  • init, doctor and upgradeA project with CI, every missing tool with its fix, pins moved in one step.
  • Teaching diagnosticsEvery macro error says what, why and how to fix it.
  • Reconnect everywhere (ADR-051)Apps on all three platforms reconnect to undra dev by themselves.

Testing

  • A testing kit for apps (ADR-055)Previews on the real core; recorded sessions replay in tests.
  • The contract gridThe same scenarios against the real core on Swift, Kotlin and TypeScript, every cell passing.
  • Adversarial reviewsEvery core crate and every feature, reviewed by someone who did not write it.

Size and speed

  • The JavaScript runtime at 16 KB (ADR-057)What a page loads up front went from 22.1 KB to 15.8 KB gzipped.
  • The web core under 120 KB (ADR-052)The hello-world wasm, measured and gated in CI.
  • Native size profile and gates (ADR-052)Release builds tuned for size; opt_level chooses smaller or faster.
  • The web call path (ADR-056)A generated TypeScript call went from 3.2–3.5 µs to 0.47–0.68 µs.
  • Frame-coalesced delivery (ADR-031)Each mirror applies what arrived once per frame.
  • Harsh-conditions benchmarksFirehose, churn, fan-out, backpressure and a soak, with CI gates.

Production

  • Panic reports and symbols (ADR-046)A contained panic reaches the app with frames undra symbolicate reads.
  • Background runs (ADR-046)The offline queue drains under the OS's deadline.
  • A runtime ends when its owner lets go (ADR-034)Off-core writes are refused; a panicking computed poisons only itself.

Docs and samples

  • Cookbook and migration guidesRecipes, and the way over from Kotlin Multiplatform and UniFFI.
  • FieldbookA production-shaped sample beyond the playground.
  • API referenceSwift, Kotlin and TypeScript from the generated code; Rust from rustdoc.
Next

Planned next

recorded as open

Each of these is recorded as open in the repository, with the work done around it. A plan, not a promise; the order may change.

  • Adapter conformance across platforms

    The five SSE adapters merge the core's headers differently, and the JDK Http adapter drops restricted headers where Swift passes them. One vector file recorded against one server and diffed in CI, like the fakes' conformance file, after a rule in the specification says which header wins.

  • Benchmarks on physical phones

    Every device row so far is from a simulator, an emulator or headless Chromium. Real-phone rows next, then budgets for them and a CI job.

  • Maven Central and the npm registry

    The conventional registries, after launch, beside GitHub: the Kotlin runtime on Maven Central and the npm packages on the registry. undra upgrade moves a project over. crates.io follows, under a registry-safe prefix.

  • Homebrew (brew install undra)

    Through homebrew-core, once the repository is 30 days old and notable (75 stars, or 30 forks or watchers). There is no tap at launch: the installer and cargo are the two ways to get the CLI.

  • Android modules tested in CI

    undra-compose, android-adapters and android-work pass locally and on the emulator; an emulator job in CI runs them.

  • Android under Bazel, verified

    The rules declare Android; a build and a test run prove it.

  • Byte-reproducible undra build

    Today the same core built in two directories differs, because cargo hashes the absolute path into crate names.

  • The examples on schema diff

    Commit each example's schema.json, so the repository reviews its own API changes the way it asks apps to.

  • Cancelled port calls reach the platform

    A cancelled call is abandoned in the core today while the platform's request runs on. Its own decision record first.

  • Your network stack, proved further

    Certificate pinning through OkHttp end to end, a build against OkHttp 5, and the iOS WebSocket adapter refusing a background session as the SSE adapter does.

  • Smaller Android libraries

    Relocation packing saves about 3%, once a load test on API 23 passes.

  • Windows CLI

    Release binaries and docs for the undra command on Windows.

  • A custom domain

    A home for the site and docs that is the project's own.

Later

Later

approved, not started

Decided in direction and waiting their turn.

  • Dart and Flutter bindings

    A fourth host after React Native, which proved the pattern. Not started.

  • Desktop as a first-class target

    Compose Desktop and macOS samples built in CI over the runtimes that exist; Windows and Linux over the same C ABI.

  • Xcode 27

    The Swift test target was reported not to build on Xcode 27. Our machines and CI run Xcode 26; it is fixed once it reproduces.

Exploring

Exploring

ideas, not scheduled

Questions the project is asking, not plans.

  • A GraphQL story

    Undra has no GraphQL layer; an app built around Apollo keeps Apollo on the platform side.

  • A sync engine

    If it comes, a separate package, not part of the core.

  • Compose Multiplatform interop

    An Undra core under a Compose Multiplatform UI.

Not planned

Not planned

Shared UI of any kind, and hosted services. Undra owns everything under the pixels and leaves the screens to SwiftUI, Compose, React and React Native.