Reviews → Social MVP scaffold.
cp .env.example .env
npm install
docker compose up -d postgres redis
npm run db:migrate
npm run db:health
npm run dev
# in another terminal
npx ts-node worker/index.tsOr run everything in containers:
cp .env.example .env
docker compose up --builddocker compose up runs a one-shot migrate service first, then starts web and worker after migrations complete.
- Migration tool: lightweight TypeScript runner (
scripts/migrate.ts) executing SQL files fromdb/migrations. - Apply migrations:
npm run db:migrate - Health check query:
npm run db:health - Query helper:
lib/db.ts(query(...)overpgpool)
- UI page:
/import - Create/select a business, upload CSV, and import reviews into
reviewswithsource="manual". - Supported CSV columns:
- required:
rating,text,reviewed_at(ISO) - optional:
author_name
- required:
- UI page:
/quotes - Runs a deterministic selector for a business and persists top-N quote candidates in
draft_posts. - Heuristics:
- prefer 4–5 star reviews
- prefer 30–200 character quotes
- reject profanity matches
- boost keyword matches (
food,service,clean,friendly, etc.)
- Caption generation endpoint returns 3 AI variants (
friendly,premium,playful) and lets you save selected caption todraft_posts.caption_text. - Branded image rendering endpoint generates PNGs in local storage (
public/generated) and saves path todraft_posts.image_path. - Requires
OPENAI_API_KEYin environment for caption generation.
- UI page:
/approval - Lists draft posts grouped by status (
draft,approved,scheduled) - Supports transitions:
- draft -> approved
- approved -> draft
- Supports setting
scheduled_fordatetime for approved drafts. - Persists optional
audit_noteand updatesupdated_aton each transition.
- Worker entrypoint:
worker/index.ts - Automatically runs quote selection -> caption generation -> image render for each business on a timer.
- New draft candidates are created in
draft_postswith:quote_textfrom selectorcaption_textfrom caption generator (friendly variant)image_pathfrom renderer output
- Duplicates are avoided by skipping reviews already linked to an existing draft.
- Scheduler adapter interface:
lib/integrations/scheduler.ts - Stub implementation logs structured scheduling payload and returns
scheduled. - Worker command:
npm run worker:schedule- picks up rows with
status='approved'and duescheduled_for - marks rows
status='scheduled'after adapter call
- picks up rows with