A single-user, self-hosted kanban app for managing YouTube videos from idea to publish.
Keep every video idea in one place, draft your script in a rich markdown editor, track production with checklists, and move work through a pipeline that matches how you actually make videos — all with automatic version history so no script is ever lost.
Runs as a web app (LAN-accessible from any browser or phone) or as a Windows desktop app (Electron). Single user, no accounts, no cloud dependency.
Designed like a quiet edit bay at night: an "Edit Bay" theme with teal-and-orange post-production color grading, Space Grotesk display type, and a film-leader countdown mark.
- Columns matching your pipeline: Ideas → Drafts → Script → Script Polished → Titles → Thumbnails → Record / Edit → Published
- Drag & drop cards between and within columns (persists instantly)
- Quick-add an idea with just a title — two seconds to capture a thought
- Card faces show title, priority, tags, target date (red if overdue / amber within a week), thumbnail preview, checklist progress, and a completed state
- Complete toggle moves a card to the Published terminal column and stamps it done
- Editable title, priority (P1/P2/P3), target date picker, media/game, series
- Tags split into Personal vs YouTube kinds, with autocomplete and a one-click "Copy YouTube tags" button for pasting into YouTube Studio
- Reference links — ordered list, reorder, open in new tab
- Title ideas — brainstorm, reorder, star a chosen one, set it as the card title
- Thumbnail — upload/swap/remove an image (shown on the card face too)
- Archive any card
- TipTap rich-text editor that reads/writes markdown (headings, bold/italic/strikethrough, lists, task lists, quotes, code, links)
- Markdown input shortcuts (
#→ heading,**bold**,-→ list,- [ ]→ task) - Full undo/redo (Ctrl+Z / Ctrl+Shift+Z)
- Autosave (2s debounce) with a subtle "Saved" indicator
- Live word count and estimated read-aloud time (words ÷ 145 wpm)
- Automatic snapshots on autosave (max once per 10 min), stage change, and manual save
- Version history panel with line-level diff (added green, removed red)
- Restore is never destructive — your current script is snapshotted before restoring
- Keeps the last 50 autosave versions per card; manual/stage-change versions kept forever
- Add/edit/delete/reorder/check off items with a progress bar
- Save any checklist as a reusable template, apply templates to any card (deduped)
- Ships with a "Standard edit" template matching your real edit workflow
- Search (Ctrl+K) across titles and scripts
- Tag filter bar to focus the board on one lane
- Archive view — restore archived cards anytime
- Calendar view — see cards by target date, drag a card onto a day to re-date it
- Dedicated Brainstorming tab with separate idea backlog
- Capture, score, tag, group, and triage ideas (
inbox,exploring,shortlisted,parked,discarded,promoted) - Import from the board
Ideascolumn into brainstorming - Promote vetted ideas into the board pipeline, carrying note/tags/links
- Connect Google OAuth and sync channel/video metrics into local DB
- Dashboard with daily views trend, insights, and video-to-card linking
- Format-aware analytics views for Shorts vs long videos, plus engagement/retention benchmarks
Grab the latest installer from releases/ (VideoBoard-1.0.0-setup.exe), run it, done.
Data is stored in %APPDATA%\videoboard.
npm install
npm run dev- Board: http://localhost:5173
- API: http://localhost:3456
On your LAN, open http://<your-machine-ip>:3456 from any device (set HOST=0.0.0.0 if needed) — works from your phone for quick idea capture.
npm run build
npm start # serves the built app at http://<host>:3456Config via env: PORT (default 3456), HOST (default 0.0.0.0), VIDEOBOARD_DATA_DIR (default ./data).
npm run electron # build + launch in Electron (dev desktop run)
npm run dist # build + produce Windows NSIS installer into releases/
npm run dist:dir # build + unpacked app into releases/win-unpackedTo ship a new version: bump "version" in package.json, then npm run dist.
The installer lands in releases/VideoBoard-<version>-setup.exe.
The Android client uses Capacitor to package the existing web app.
npm run android:sync # build web assets + sync to android project
npm run android:open # open android/ in Android StudioTo point the mobile build at a LAN/cloud API, set VITE_API_BASE_URL before syncing.
Android sync/build currently needs a JDK in the Java 21-24 range. The workspace
Java 25 runtime triggers a Gradle classfile error, so switch JAVA_HOME before
running a release build if you hit that failure.
PowerShell example:
$env:VITE_API_BASE_URL = "http://192.168.0.240:3456"
npm run android:syncThen run from Android Studio on a device/emulator. API CORS is enabled in the server for Capacitor WebView origins.
- SQLite database via Node's built-in
node:sqlite(single filevideoboard.db) - Thumbnails stored under
uploads/ - Data directory resolution:
- Web server →
./data(orVIDEOBOARD_DATA_DIR) - Desktop app → Electron
userData(%APPDATA%\videoboard)
- Web server →
There's a single config module for this (src/server/db/index.ts), so moving between web and desktop needs no code changes.
| Layer | Tech |
|---|---|
| Frontend | React 18, Vite, TypeScript, Tailwind CSS, dnd-kit (drag & drop), TipTap (editor) |
| Backend | Node.js, Fastify, REST API |
| Data | SQLite (node:sqlite) + Drizzle ORM |
| Desktop | Electron + electron-builder (NSIS installer) |
| Diff | diff package for version history |
The frontend talks to the backend only over HTTP — no direct DB access — which is what makes the Electron packaging trivial (Electron just embeds the same Fastify server and loads the built frontend from it).
videoboard/
├── src/
│ ├── server/ # Fastify backend
│ │ ├── index.ts # server bootstrap + static serving
│ │ ├── db/ # schema, migrations, seed, versions, node:sqlite adapter
│ │ ├── routes/ # /api/board + /api/cards/* REST routes
│ │ └── shared/types.ts # shared TypeScript types
│ └── client/ # React frontend (Vite)
│ └── src/
│ ├── App.tsx # board + view switching
│ ├── components/ # board, card detail, editors, modals, ui primitives
│ └── lib/ # api client, diff util, cn()
├── electron/
│ └── main.mjs # Electron main process (embeds server, opens window)
├── electron-builder.yml # desktop packaging config
├── vite.config.ts
└── package.json
npm run dev # start backend (tsx watch) + frontend (Vite) together
npm run typecheck # typecheck server + client
npm test # server + client integration/smoke tests
npm run test:e2e:smoke # runtime browser smoke checks (Playwright)
npm run ci # fast CI gate (typecheck/docs/tests/build/perf)
npm run ci:extended # ci + runtime browser smoke
npm run build # compile server + build frontenddocs/USER_GUIDE.md— how to use the app day to daydocs/API.md— REST API reference
- Single user by design — no accounts, no auth, no multi-user sync.