Rust workspace: videoeditor — scripted short-video renderer (markdown in,
vertical video out via headless Chrome + ffmpeg + ElevenLabs).
crates/videoeditor— CLI + scene orchestration; embedstemplates/andformats/(extracted to~/.cache/videoeditor/<version>/at runtime;VIDEOEDITOR_ROOToverrides).crates/videoeditor-timeline— script.md parser →Episode/Scene/Clip.crates/videoeditor-chrome— CDP driver (long-lived headless Chrome; NEVER single-shot--screenshot, it hangs on macOS).crates/videoeditor-media— all ffmpeg/ffprobe invocations + assembly.crates/videoeditor-voice— ElevenLabs TTS/STT (ELEVENLABS_API_KEY).crates/videoeditor-genai— typed image-generation clients: xAI Grok Imagine (XAI_API_KEY, reference images) + Google Imagen (AI_STUDIO); Veo/Grok video is the planned next tenant.crates/videoeditor-record—recordsubcommand: local web recorder (tiny_http REST server); takes transcode via ffmpeg intoaudio/clips/. Serves the UI fromui/— a COMMITTED trunk build of the next crate. Never editui/by hand;just e2eregenerates it automatically andjust checkfails if it's stale vs the UI source (ui/.source-hash). This crate publishes to crates.io WITH the dist — installs need no wasm.crates/videoeditor-record-ui— the recorder front end: Leptos (CSR) → wasm via trunk.publish = false: not standalone, its build output ships inside videoeditor-record.nix developprovides trunk/wasm-bindgen-cli (thewasm-bindgencrate pin must match the CLI version — bump together). Regenerate the dist only via the nix toolchain (nix develop --command just ui) so bytes stay stable.e2e/— Playwright suite for the recorder (just e2e, rebuilds the UI first): drives the real binary + real Chromium with a fake mic through record → coach → keep → approve. UI changes are not done until it passes.examples/hello-bench— smallest end-to-end episode; keep it rendering.
-
Nix is the preferred dependency path:
nix develop(dev shell; puts a source-freshvideoeditoron PATH) /nix build .#videoeditor(the install artifact CI gates on). Details: docs/nix.md. Keepflake.lockcommitted;nix flake updateonly as a deliberate PR. -
just check— clippy -D warnings + fmt --check (CI runs the same recipe). -
just test/cargo test --workspace— parser + fit-check tests live in videoeditor-timeline. -
After ANY voice or timing change: re-run tts → heed the fit-check warnings (
⚠ narration overlap/truncated) → recompute scene durations → re-render. -
cargo run -p videoeditor -- build examples/hello-bench— end-to-end smoke (needs Chrome, ffmpeg, ELEVENLABS_API_KEY).
- Scene templates are PURE functions of (data, t) — no CSS animations, no
timers, no network. Everything derives from
SCENE.dandSCENE.t. - Templates resolve in layers: episode dir → frontmatter
packs:→$VIDEOEDITOR_PACK_PATH→ built-ins (videoeditor pack list <ep>shows provenance). Users never hand-roll templates —pack initscaffolds a pack whosetemplates/CLAUDE.mdis the authoring contract; author templates WITH the user per that file. - Releases go through release-plz (PRs to main; never bump versions by hand).
- Never commit media renders or API keys. Committed images go through git-lfs.
- Production craft for episode content lives in crates/videoeditor/guide.md
(embedded; printed by
videoeditor guide) — the single source of truth. Never duplicate its rules into other docs; point at the command instead.