Skip to Content
ContributingRelease flow

Release Flow

FrankenTUI is a 20-crate workspace, and only three crates are currently on crates.io: ftui-core, ftui-layout, and ftui-i18n. The other 17 are in the publish queue. This page explains the staging strategy, why the ordering exists, and how to consume the workspace while the transition is in progress.

This is an explanation page, not a how-to. For consumer-side setup, see installation and project setup. For the no-outside-merges policy that governs contributions, see project philosophy.

Expect the “3 of 20” number to change as the queue drains. The underlying policy — publish in dependency order, don’t publish until the API is stable enough to promise SemVer — does not.

Why three crates first

The published trio is not arbitrary. They sit at the bottom of the dependency DAG and are the most stable:

CrateWhy first
ftui-coreTerminal lifecycle + event types. Depended on by everything else. Its API has been stable the longest.
ftui-layoutConstraint solvers + pane workspace. Large crate, but its public surface is well-scoped and doesn’t churn.
ftui-i18nSmall crate, no dependents in the workspace. Safe to publish in isolation.

The render crate, runtime crate, and widget crate are higher up the dependency stack. Their public APIs are still moving, and pushing them to crates.io prematurely would lock in shapes we’ll want to change.

Mental model

Read upward: crates higher in the diagram depend on crates lower in the diagram. Publishing proceeds bottom-up so that when the upper crates reach crates.io, their deps are already resolvable.

Current status table

Cratecrates.ioVersion policy
ftui-corePublishedTracking workspace version
ftui-layoutPublishedTracking workspace version
ftui-i18nPublishedTracking workspace version
ftuiQueuedPublishes after runtime + widgets
ftui-backendQueuedPublishes with render
ftui-styleQueuedPublishes before widgets
ftui-textQueuedPublishes before widgets
ftui-renderQueuedPublishes with style + text
ftui-runtimeQueuedPublishes after render + core
ftui-widgetsQueuedPublishes after style + text + render
ftui-extrasQueuedPublishes after render
ftui-ttyQueuedPublishes with backend
ftui-webQueuedPublishes with backend + render
ftui-showcase-wasmProbably internalBuild target, not a library
ftui-demo-showcaseProbably internalApp, not a library
ftui-harnessQueuedPublishes after runtime
ftui-ptyQueuedPublishes independently
ftui-a11yQueuedPublishes independently
ftui-simdReservedNot published until API settles
doctor_frankentuiQueuedPublishes as a binary tool

The migration story

The plan, in order of priority:

  1. Stabilize the bottom crates. Publish ftui-core, ftui-layout, ftui-i18n — done.
  2. Publish the rendering stack. ftui-style, ftui-text, ftui-render, ftui-backend. These are close to stable; expect them next.
  3. Publish the runtime. ftui-runtime and ftui. These need one more pass to settle the Cmd and Subscription surfaces.
  4. Publish the widget library. ftui-widgets, ftui-extras, ftui-a11y. Widgets cluster late because their API surface is largest and most user-facing.
  5. Publish the ancillary crates. ftui-tty, ftui-web, ftui-harness, ftui-pty, doctor_frankentui.
  6. Keep ftui-simd reserved. API is not yet settled; will publish when the feature set is nailed down.

Not on crates.io, probably ever: ftui-showcase-wasm and ftui-demo-showcase are apps/build targets, not libraries. They’ll live in the workspace as runnable binaries.

Version policy

Published crates track the workspace version number. When a workspace-wide bump happens, all published crates bump together. Individual crates do not have independent version lines.

SemVer applies — but the project is pre-v1, so minor bumps can still contain breaking changes. Once ftui hits 1.0.0, the policy tightens: breaking changes only in major bumps, deprecation notes in minor bumps, and minimum 30-day deprecation windows.

We are not at v1 yet. Do not assume SemVer-major-bump-equals- breaking semantics right now. Pre-v1 is explicitly “break things when we need to.” See design decisions for the backwards-compatibility policy.

How to consume the workspace today

While the queue drains, the recommended approach is workspace path dependencies:

Cargo.toml
[dependencies] ftui = { path = "../frankentui/crates/ftui" }

See project setup for the full pattern, including per-crate feature flags and the release-profile exception for ftui-extras.

If you want to consume only the published subset from crates.io, that works for ftui-core, ftui-layout, and ftui-i18n — but you’ll need path deps for anything else, and mixing sources for the same crate creates type-unification issues. Pick one source per crate, consistently.

CI and publishing mechanics

Crates publish via CI from the workspace main branch when a version tag is pushed. The pipeline:

  1. Tag pushed: git tag v0.3.2 && git push --tags.
  2. CI runs the full verification contract: check, clippy, fmt, test, snapshot, determinism soak, coverage gate.
  3. CI publishes each queued crate in dependency order.
  4. If any step fails, publishing stops at the failing crate and waits for a fix commit.

CI never publishes from branches other than main. The master branch is kept in sync with main for legacy URL compatibility, not as a release branch.

Pitfalls

Don’t depend on the queue order as a schedule. The order above is the current intent. Real-world release cadence depends on API stabilization — a crate that isn’t ready simply waits.

Don’t mix published and path deps for the same crate. If you have ftui-core = "0.3" in one place and ftui-core = { path = ... } in another, Cargo treats them as distinct types. Pick one source per crate and use it everywhere.

Don’t pin a published crate to an old version while using path deps for the rest. Published versions track the workspace, so a pinned old version will desync from path-deps that followed the workspace forward. Pin all or none.

Where next