Dashboard
A Next.js app in web/ that shows every business profile: outliers, fastest posts, rising posts and tracked links as cards (thumbnail, labels, metrics, growth sparkline, hook, transcript), plus the AI ideas notes, a swipe-file board and source health.
It runs in two modes:
| Local (your PC) | Published (Vercel, free Hobby plan) | |
|---|---|---|
| Start | cd web && npm install && npm run dev → http://localhost:3210 |
scripts/publish.ps1 |
| Data | web/data/*.json, refreshed after every run |
a snapshot uploaded with each deploy |
| Save / Track / Dismiss / swipe status | run the Python CLI and update the vault | read-only; the buttons copy the CLI command |
| Login | none (unless SITE_PASSWORD is set) |
password (SITE_PASSWORD); locked if it's missing |
Nothing runs in the cloud. Collection stays on your PC (home IP, yt-dlp, the scheduled task). Vercel only hosts the pages.
Data flow
python -m viral_scout run <profile> → data/<profile>-latest.json + SQLite
└─ export (automatic after each run) → web/data/<profile>.json, web/data/index.json
python -m viral_scout export [profiles] → the same, by hand
scripts/publish.ps1 → export + vercel deploy --prod (uploads web/ incl. data/)
web/data/ is git-ignored, so the public repo never contains business data. The deploy uploads it straight from your PC: web/.vercelignore deliberately doesn't exclude it.
Publish to Vercel
One-time setup:
npx vercel login # once per PC
scripts/publish.ps1 -SetPassword # links project "viral-scout", asks for a password, deploys
Afterwards:
scripts/publish.ps1 # export + production deploy
scripts/publish.ps1 -Preview # preview URL instead
To publish automatically after the daily run, add a line to your scheduled task after run-daily.ps1:
pwsh -File scripts/publish.ps1.
Free plan notes:
- Vercel Hobby is meant for personal, non-commercial use. If the dashboard becomes a client deliverable, move it to Pro.
- Vercel's own "Password Protection" is a paid feature, so this app has its own login: an HMAC-signed cookie, valid 30 days. It runs in
src/proxy.ts, Next 16's replacement for middleware. - Every page is pre-rendered at build time. The only server code that runs is the login check, which fits comfortably in the free limits.
Pages
/search: searches titles, hooks, endings, transcripts and captions. Locally it covers the full history of every business through the Python CLI; the published site searches the latest runs in the browser./new: New research. Pick Quick research (a one-offresearch-…profile, reports go to the repo'sreports/) or New project (reports go to an Obsidian project folder you pick). Describe the business or topic and add search phrases. Hashtags, the topic filter and the spam rules are derived for you, and the first run starts in the background while the page shows its progress. Local only./setup: every API key with what it unlocks, its cost, how to get it and a docs link. Paste, Save and Test it. Keys go into.envon your PC through stdin (never on the command line) and are always shown masked. Local only; the published site never manages keys./p/<profile>/performance: Your performance. Your own videos and ads: KPI cards grouped A–E (hover for formula and denominator), an organic / paid toggle, the 5 tests per video, a retention curve with drop-off markers, the diagnosis, priorities, unit economics and CSV import steps. Read-only; data fromweb/data/perf/<profile>.json. See performance.md./: one card per business, with posts, outliers, 🔥 mega, saved, and the top thumbnails./p/<profile>has these tabs:- Outliers, Fastest, Rising now, Tracked: card grids with search, a platform filter and "hide saved".
- Ideas: the
<date>-viral-ideas.mdnotes written by the/viral-scoutskill, rendered as HTML. - Swipe file: a board with idea → scripted → filmed → posted → skip columns. Changing a card's status locally edits the note's
status:in the vault. - Sources: skipped sources, suggested hashtags, creators who keep showing up, errors and recent runs.
/p/<profile>/ads(the Ads button on the business page): the ads scout (ads-scout.md). It shows an advertiser table (click a row to filter), then ad cards with the creative, advertiser, days running, variants, reach, platforms, hook, offer, CTA, landing domain and labels. You can filter by advertiser, format and offer, sort by score, days, variants or newest, and show only ads that are still running. Below the cards: offers that keep running, coverage, skipped sources (with the key that unlocks each) and lookup links. It's read-only, fromweb/data/ads/<profile>.json, whichpython -m viral_scout ads|exportwrites. Meta snapshot URLs, which carry the access token, are never exported.
Security
- Local actions only accept requests whose host is
localhostor127.0.0.1. The Python CLI is called with fixed arguments, never through a shell. - On Vercel (
VERCELis set) actions are switched off, and the API answers 403. - Pages send
X-Robots-Tag: noindexand setrobots: noindex.