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

The output is a complete crate you can build with Trunk:
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

Build

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

  • / 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

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.