Local-first Mac tool for producing narrated lesson videos: import a deck and a
script, record voice against a teleprompter, produce a 1080p MP4 with SRT
captions. README.md covers what it does and why; this file covers how to work
on it.
npm run dev # server and app together, watch mode
npm start # build the app, serve it from the server on one port
npm test # vitest, whole workspace
npm run typecheck # tsc -b across shared, server, app
npm run doctor # environment check (ffmpeg and friends)
npm run package:build # build the distributablenpm run typecheck is a project-references build across three workspaces, so it
catches breakage that npm test alone will not. Run both before calling work
done.
Three npm workspaces with a deliberate dependency direction: shared holds
types and pure logic, server does the file, audio and ffmpeg work, app is
the UI. Nothing in shared may import from server or app.
Specs and plans live in docs/superpowers/specs and docs/superpowers/plans.
The user guide is docs/guide.md and is linked from the README, so a change to
how the tool is driven means updating the guide in the same commit.
No cloud, no accounts, no uploads. The user's voice and content stay on the Mac. That is the reason the tool exists, stated on the front of the README. Do not add a network call, a telemetry ping, a hosted model or an upload step, and treat any dependency that phones home as disqualified.
originis GitHub. This is the public project.giteais the private NAS instance, reachable over Tailscale.lanis that same NAS over the home network address, which resolves only at home.
Check which remote you mean before pushing. A push meant for the NAS that lands
on origin is public and cannot be taken back. For the same reason, keep
anything private out of this repo entirely: internal hostnames and addresses,
infrastructure notes, and client or course material. Those belong in
shared-foundations or the product repos, none of which are public.
A lesson is scenes, one slide plus one script block each, and the video is rebuilt from whatever changed: fix one scene's audio and only that scene is re-encoded. When touching the render path, preserve that property. A change that makes a full re-encode the normal case defeats the tool's main advantage over the cloud editors it replaced.