Skip to content

Forum / Q&A — implementation & runbook

Design rationale lives in ../FORUM_PROPOSAL_2026-06.md. This file is the operator runbook.

What shipped

Backend (worker):

  • migrations/0034_forum.sql — questions, answers, votes, tags, reports, AI approval outbox, and the disclosed cinevva-assistant user.
  • src/db/forum.tsForumDB data access.
  • src/forum/index.ts — request handlers (list, detail, ask, answer, vote, accept, report, admin AI-draft queue).
  • src/forum-ai.ts — AI responder: drafts answers into the approval outbox and posts approved drafts as the Cinevva Assistant. Wired into the 2-minute cron in src/index.ts.
  • Routes mounted under /forum/* in src/index.ts (reuse session auth, admin gate, chat moderation + cost logging).

Frontend (site):

  • ../.vitepress/components/ForumPage.vue — live list + detail + ask/answer/vote UI.
  • ../forum.md — mounts the component at /forum; nav link added under "Learn".

Content + SEO:

  • scripts/forum-seed.mjs — generates scripts/forum-seed.sql: curated, anonymized real Q&As (source='seed', published).
  • ../scripts/build-forum-pages.mjs — pre-renders answered questions to crawlable forum/q/<slug>.md with JSON-LD QAPage. This is the SEO asset (runtime-fetched content is not indexable).

Deploy

bash
# 1. Apply the schema (remote D1)
cd worker
npx wrangler d1 execute <DB_NAME> --remote --file migrations/0034_forum.sql

# 2. Seed real Q&As so the forum is never empty
node scripts/forum-seed.mjs > scripts/forum-seed.sql
npx wrangler d1 execute <DB_NAME> --remote --file scripts/forum-seed.sql

# 3. Deploy the worker (adds /forum/* routes + AI cron)
npx wrangler deploy

# 4. Pre-render the SEO pages, then build the site
cd ..
node scripts/build-forum-pages.mjs && npm run build

Use the same <DB_NAME> as the other migrations (see wrangler.toml d1 binding).

Operating the AI responder

Launch posture is approval-gated: nothing the AI writes goes live without an admin approving it.

  • The cron drafts an answer for each unanswered user question into forum_ai_outbox (status pending_approval).
  • Admin reviews the queue: GET /forum/ai-drafts (admin session or none — gated by isUserAdmin).
  • Approve/reject: POST /forum/ai-drafts/<id>/decide with {"decision":"approved"} or "rejected".
  • The next cron run posts approved drafts as the Cinevva Assistant (is_ai=1, rendered with an "AI" badge), and skips any question a human already answered.

To relax to delayed-fallback later (AI answers only if no human has within N hours), change getQuestionsNeedingAiAnswer to add an age filter and auto-approve in draftForumAnswers. Keep the disclosure label regardless.

Scaling the seed corpus

The starter set is 16 curated pairs across all 8 categories. To reach the 150–250 estimated in the proposal, run an LLM extractor over the live game_messages table (cluster recurring questions, pair with the in-transcript assistant reply, anonymize) and append rows to forum-seed.sql in the same shape.

Endpoints

Public: GET /forum/categories, GET /forum/questions, GET /forum/questions/:slug. Auth: POST /forum/questions, POST /forum/questions/:id/answers, POST /forum/vote, POST /forum/accept, POST /forum/reports. Admin: GET /forum/ai-drafts, POST /forum/ai-drafts/:id/decide.