Local review/queue/publish app for the Solid Plumbing & Electrical video pipeline.
Render pipeline finishes a video → pushes it to this app's DB → you review/approve/reorder in a browser dashboard → an hourly (or on-demand) Claude scheduled task publishes the approved queue to YouTube, Instagram, Facebook, and TikTok simultaneously via the Metricool MCP connector.
Videos are produced with a separate HyperFrames-based pipeline following the
"Solid Plumbing & Electrical" brand instructions (brand kit, editing taste,
delivery specs, etc. — see the md/ docs in the parent project). Once a
video is rendered, it needs a place to land, get a human sanity-check, and
go out to all four platforms at once without manual re-uploading per app.
solid-que is that piece: DB + review UI + queue + publish trigger, built as
its own standalone app (separate repo: dacoders77/solid-que) so it can run
continuously regardless of what else is happening in the video-generation
project. It's expected to keep growing new features over time.
These came out of working through the requirements before building:
- Stack: Node.js/TypeScript + SQLite (
node:sqlite, no native build step) — matches the JS-heavy video pipeline, and SQLite needs zero setup. - Always-on hosting: runs as a Windows service (see below) so it survives reboots and doesn't need a terminal window open.
- Ingestion: the render pipeline pushes directly to the DB via a local API call right after rendering finishes — no folder-watching/polling.
- Storage: the ingest step moves the rendered file into the app's own managed storage folder; it never duplicates it.
- Review: single-user login-gated dashboard, reachable via plain port-forwarding (not just localhost) since access is needed from outside the home network. No VPN/tunnel layer — just app-level login for now.
- Queue control: not just FIFO — approved videos can be reordered (move up/down), postponed, and given an explicit scheduled publish time.
- Publish mechanism: the Node app cannot call the Metricool MCP connector itself (MCP tools are only callable from a Claude session). So publishing is handled by a Claude scheduled task that polls the app's API and publishes via the already-configured Metricool connector — hourly, plus on-demand when triggered manually from the dashboard.
- Per-video metadata tracked: title, description, thumbnail, transcript, source project, and one link per platform (YouTube/Instagram/Facebook/ TikTok) so you can jump straight to the live post after publishing.
- Every video publishes to all 4 platforms at once — no per-platform toggle (kept simple; can add later if needed).
- Git workflow: commits and pushes for this repo are handled directly, without asking for confirmation each time (per your instruction).
- Node.js + TypeScript, Express
- SQLite via Node's built-in
node:sqlite(no native build tools required) - Single-user session login (username + scrypt password hash)
- Plain HTML/vanilla JS dashboard (no frontend framework)
npm install
npm run build
cp .env.example .envGenerate a password hash and paste it into .env as AUTH_PASSWORD_HASH:
node dist/scripts/hash-password.js "your-password-here"Edit .env: set SESSION_SECRET to a long random string, AUTH_USERNAME,
and confirm DB_PATH / STORAGE_DIR.
Run it:
npm startOpen http://localhost:8787 (or your configured PORT).
The render pipeline calls this once a video is done. It moves (never copies)
the video file into managed storage and creates a pending_review row.
curl -X POST http://localhost:8787/api/videos/ingest \
-H "Content-Type: application/json" \
-H "X-Service-Token: $SERVICE_TOKEN" \
-d '{
"title": "5 Ways To Save On Your Water Bill",
"description": "...",
"transcript": "...",
"source_project": "trade-1",
"video_path": "C:/path/to/rendered/video.mp4",
"thumbnail_path": "C:/path/to/thumbnail.jpg"
}'This and the /api/publish/* routes authenticate with the X-Service-Token
header (matching SERVICE_TOKEN in .env) instead of a browser session,
since they're called by scripts/agents, not a logged-in user.
POST /api/videos/ingest— register a finished videoGET /api/videos/pending— videos awaiting reviewPOST /api/videos/:id/approve— moves a pending video into the queuePOST /api/videos/:id/reject— deletes the file + DB rowGET /api/queue— ordered queuePOST /api/videos/:id/move—{ direction: "up" | "down" }, reorder in queuePOST /api/videos/:id/postpone—{ until: ISO date string }POST /api/videos/:id/schedule—{ scheduled_time: ISO date string }GET /api/publish/due— queued videos ready to publish now (used by the Claude scheduled publish task)POST /api/publish/:id/start— mark aspublishing(avoids double-processing)POST /api/publish/:id/result— report back platform links + success/failure
The simplest path is NSSM:
-
Download NSSM, put
nssm.exesomewhere on PATH. -
npm run buildfirst sodist/server.jsexists. -
Install the service:
nssm install solid-que "C:\Program Files\nodejs\node.exe" "C:\path\to\solid-que\dist\server.js" nssm set solid-que AppDirectory "C:\path\to\solid-que" nssm set solid-que AppEnvironmentExtra NODE_ENV=production nssm start solid-que
NSSM restarts the process automatically on crash and starts it on boot.
You said you want to reach the dashboard from outside your home network via plain port-forwarding + login. Practical notes:
- Forward your router's chosen external port to this machine's
PORT. - The single-user login is the only gate — keep
SESSION_SECRETand your password strong, since this is reachable from the open internet. - Consider adding HTTPS (e.g. a reverse proxy like Caddy with a free Let's Encrypt cert) once this is more than a personal testing setup — plain HTTP means your session cookie/password travel unencrypted.
This app cannot call the Metricool MCP connector itself — only a Claude session can. The publish step is a Claude scheduled task (hourly + on-demand) that:
- Calls
GET /api/publish/due. - For each due video, calls
POST /api/publish/:id/start. - Publishes to YouTube, Instagram, Facebook, TikTok via the Metricool connector.
- Calls
POST /api/publish/:id/resultwith the resulting post links (or the error, on failure).
Not wired up yet — this needs a public IP/port-forward address first, so the scheduled task can reach the app's API and Metricool can fetch the video/thumbnail files over the internet (localhost URLs won't work for Metricool's side). Postponed until that's in place.
Built so far: DB schema, ingest API, review/queue API + dashboard, publish worker API endpoints, service-token auth for machine callers, and Windows service deployment docs. Smoke-tested locally (login, ingest with real file move, approve/reorder/postpone, static file serving, auth gates).
Still open:
- Public IP / port-forward setup (blocks the Claude scheduled publish task)
- Wiring the actual Claude scheduled task once the above is ready
- HTTPS in front of the port-forwarded app (currently plain HTTP)
- Windows service install on the target machine (docs are ready, not yet run)