Studio Eject

Studio’s Leptos+Trunk UI lives in the framework repo, but you don’t have to consume it from there. Phase 2 ships two ways to take it with you:
  1. cratestack studio eject — copies the UI sources into a writable directory you can fork.
  2. embed-ui cargo feature — bundles the Trunk release output into the Studio binary, so cratestack studio run serves a real SPA with no extra moving parts.
Most users don’t need either — the upstream UI is what you’ll run on a laptop alongside cratestack studio run. Eject when you want fine control over the visual style or want to wire in actions ahead of the upstream’s schedule. Bundle when you’re shipping Studio to other people and don’t want them juggling Trunk.

Eject the UI sources

cratestack studio eject --out ./fork
# ejected studio UI to './fork' (9 files written)
# next steps: `cd ./fork && trunk serve` (with `cratestack studio run` in another terminal)
The output is a complete crate you can build with Trunk:
fork/
├── Cargo.toml          # standalone (the workspace = [] sentinel keeps it out of any parent workspace)
├── README.md           # eject-flavored: build prerequisites, dev flow, upgrade strategy
├── Trunk.toml          # proxies /api/* to the Studio backend on 127.0.0.1:7878
├── index.html
├── .gitignore
└── src/
    ├── api.rs          # fetch wrappers over the Studio read API
    ├── app.rs          # Leptos components: header, sidebar, table, drawer
    ├── lib.rs          # entry point
    └── types.rs        # wire types matching the read API
Generated artifacts (dist/, target/, Cargo.lock) are skipped, so the eject output is a clean checkout you can drop into a new git repository.

Flags

  • --out <DIR> (required) — where to write
  • --force — overwrite existing files inside --out. Without --force, eject refuses to clobber a non-empty directory.
  • --config <PATH> — currently unused by eject; reserved for future per-workspace eject customizations.

Upgrading after an eject

The eject output is a point-in-time snapshot. There’s no automated re-eject path back to upstream — a forked UI is a fork. When a new framework version ships meaningful UI changes, you’ll want to merge them manually or re-eject into a fresh directory and diff your customizations across. If your changes are upstream-friendly, please open a PR to cratestack/cratestack instead.

Bundle the UI into the binary

Phase 1b’s local-dev story (cratestack studio run + trunk serve) is fine for a single developer on a laptop, but it’s awkward to hand to a colleague. The embed-ui cargo feature solves this: build the SPA into the same Rust binary that serves the API, then ship that binary.

Build prerequisites

cargo install trunk
rustup target add wasm32-unknown-unknown

Build

cd crates/cratestack-studio/ui
trunk build --release
cd ../../..
cargo build -p cratestack-cli --bin cratestack \
  --features cratestack-studio/embed-ui --release
The first step writes crates/cratestack-studio/ui/dist/, which rust-embed reads at compile time during the second step. Skip step one and Cargo will fail at the embed step with rust-embed’s standard “folder does not exist” error, naming the missing path.

Run

cratestack studio run
# Open http://127.0.0.1:7878/ in a browser.
  • / returns the bundled index.html.
  • /api/* keeps serving JSON (mounted before the UI routes, so any future overlap resolves in favor of the API).
  • Unknown paths fall back to index.html so the browser’s client-side routing still works.

When to bundle vs. when not to

You want…Use
Quick iteration on the UI while hacking on the frameworkPhase 1b’s trunk serve (no embed-ui needed)
A single binary to give to a colleague who isn’t running Trunk--features cratestack-studio/embed-ui
Total control over the UI (custom theme, internal actions, etc.)cratestack studio eject --out ./fork, then run trunk serve in ./fork
Single binary, and a custom UIEject, customize, trunk build --release in the fork, then point the bundled-UI path at the fork’s dist/ (Phase 2.5 — not in this release)
The last row isn’t supported out of the box yet — the embed-ui feature reads from a fixed crates/cratestack-studio/ui/dist/ path. A future small change will let embed-ui point at an arbitrary dist/ directory via an env var so an ejected fork can produce a single-binary distribution.

Defaults stay light

The Studio binary’s default build doesn’t need Trunk or the wasm toolchain. embed-ui is opt-in, and eject is on-demand. If you’re just running cargo build -p cratestack-cli for the schema-validation or migration-diff CLI surfaces, none of this section applies.