Building a great tool is only half the battle. Making it usable by others is where most projects fail. Even the most elegant CLI becomes a support nightmare when handed to someone who's never opened a terminal.
By Session 12, FlowDoc had every feature we'd planned. Capture workflows, generate documentation, transcribe narration, export to Miro. But the setup story was scattered across multiple files and assumed the reader knew what they needed. A new teammate could clone the repo and still not know if their environment was ready.
The path from "it works on my machine" to "anyone can use this" required three layers: diagnostics, documentation, and interface.
Environment diagnostics first
Before writing setup guides, you need to know what can go wrong. flowdoc doctor became a 9-row environment checklist with green, yellow, and red status indicators.
The smart choice: diagnose only, never auto-install. Each failing row shows the exact command to fix it. Yellow warnings (missing mic access, no Miro token) don't fail the exit code since the core workflow still works without them.
Node.js ✓ v22.1.0
Build output ✓ dist/index.js exists
FFmpeg ✓ /opt/homebrew/bin/ffmpeg
System microphone ⚠ Using fallback device 0
Python environment ✓ .venv/bin/python (3.11.7)
Whisper dependencies ✓ transformers, torch installed
Playwright browser ✓ Chromium ready
MIRO_ACCESS_TOKEN ⚠ Not set (export MIRO_ACCESS_TOKEN=...)
The mic detection was particularly valuable. FlowDoc auto-resolves the system default microphone by parsing system_profiler SPAudioDataType and matching against ffmpeg -f avfoundation -list_devices. The doctor shows exactly which device it will use. When audio comes out choppy, this diagnostic saves the first 20 minutes of troubleshooting.
Python resolution got smarter too. Instead of requiring source .venv/bin/activate in every terminal session, FlowDoc now checks for .venv/bin/python at the repo root first, falling back to system python3. Teammates set up the virtual environment once and forget it exists.
Single path onboarding
Documentation that works assumes nothing and provides one clear path. ONBOARDING.md takes a new teammate from git clone to first narrated capture in 15 minutes with exact commands:
git clone https://github.com/budkorpenning/flowdoc
cd flowdoc
npm install && npm run build
# Python dependencies (5 min)
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
# Browser automation
npx playwright install chromium
# Environment check
node dist/index.js doctor
# Your first capture
node dist/index.js capture --url https://mantus.ai --name test-flow
No branching paths, no "you might want to" options. The guide targets developers comfortable with terminals but new to this specific tool. Domain experts get the desktop app (Session 15).
The Miro setup deserved special attention since it's the only external service. Three patterns for keeping tokens between sessions, where to find your board ID, and what the API permissions actually do. Plus an .env.example file that signals what secrets are expected without putting real ones in documentation.
The UI that changes everything
Commands like flowdoc capture --url https://example.com --name my-flow --debug work fine when you use the tool daily. They're friction when you use it monthly. A discoverable interface eliminates the "what flags do I need again?" tax.
flowdoc ui launches a minimal local web server on a random port. One card per subcommand with form fields for the required options. Live log output streams over Server-Sent Events. The two step capture flow (open browser, press Enter to start recording, Ctrl+C to stop) maps to three buttons with proper state management.
The key insight: don't rebuild the CLI logic in the web interface. The UI spawns the same dist/index.js child processes that the terminal commands use. A fix in capture logic reaches both interfaces automatically.
The architecture stayed simple. Node's built in http.createServer, vanilla HTML forms, no React or build step. Single session model where at most one command runs at a time. Generated documentation sites are served directly from the /flowdocs/* route so you can click through to them from the interface.
Server-Sent Events proved perfect for subprocess output streaming. The browser auto-reconnects, buffer replay works on page refresh, and there's no WebSocket library overhead. ANSI escape codes in subprocess output looked terrible in HTML, but stripping them server side was a one line regex.
Polish through real user testing
The UI exposed shutdown bugs that terminal usage had hidden. The two step capture UX confused people who clicked Stop before pressing Enter, leaving empty folders. FFmpeg's stdin based stopping didn't work when stdin was a pipe instead of a TTY.
Each bug taught us something about the difference between designed workflows and actual usage:
Empty captures: Disable the Stop button until recording has begun. One line change, eliminated an entire category of lost work.
Audio shutdown: Send SIGINT directly to ffmpeg instead of trying to write 'q' to stdin. FFmpeg's signal handler writes the proper file trailer and exits cleanly.
Browser hanging: Fire and forget the browser.close() call. process.exit(0) kills Chromium as a side effect anyway, and awaiting the close just creates new failure modes.
The pattern: build something that works for you, then watch someone else try to use it. Every confused moment reveals an assumption you didn't know you were making.
By Session 14, we had a tool that any developer could set up in 15 minutes and use without memorizing command syntax. The diagnostics caught environment issues before they caused mysterious failures. The onboarding guide provided one clear path. The UI made occasional usage frictionless.
That foundation made the jump to a desktop app possible. Without solid CLI tooling underneath, the Electron wrapper would have been building on sand.