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:cratestack studio eject— copies the UI sources into a writable directory you can fork.embed-uicargo feature — bundles the Trunk release output into the Studio binary, socratestack studio runserves a real SPA with no extra moving parts.
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
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 tocratestack/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
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 bundledindex.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.htmlso 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 framework | Phase 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 UI | Eject, 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) |
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.