Production Setup Guide
Production Setup Guide
Section titled “Production Setup Guide”Updated: 23/03/2026
Step-by-step guide for deploying Knowledge Hub to production.
Prerequisites
Section titled “Prerequisites”- Vercel Pro account ($20/month) — required for function durations > 10s
- Supabase account with capacity for a new project
- GitHub repository access (private,
ai-solution-hub/knowledge-hub) - API keys: Anthropic (Claude), OpenAI (embeddings)
- Domain name (optional — Vercel provides a default URL)
- Current deployment: https://knowledge-hub-seven-kappa.vercel.app
1. Create Production Supabase Project
Section titled “1. Create Production Supabase Project”- Go to supabase.com/dashboard
- Click New Project
- Select your organisation
- Configure:
- Name:
knowledge-hub-production(or client-specific name) - Database password: Generate a strong password and store securely
- Region: London (eu-west-2) — closest to UK clients
- Plan: Free tier is sufficient for pilot; upgrade if needed
- Name:
- Wait for project to initialise (~2 minutes)
- Note the Project ID, URL, and Anon Key from Settings > API
- Note the Service Role Key from Settings > API (needed for batch scripts and MCP server)
Reference project: rovrymhhffssilaftdwd (eu-west-2, London)
2. Apply Database Migrations
Section titled “2. Apply Database Migrations”From your local machine with the Supabase CLI (/opt/homebrew/bin/supabase):
# Link to the new production project/opt/homebrew/bin/supabase link --project-ref <PROJECT_ID>
# Push all migrations/opt/homebrew/bin/supabase db push
# Verify migration count matches/opt/homebrew/bin/supabase migration listExpected: 92 migration files (as of S108). Verify with
supabase migration list that all migrations have been applied successfully.
Note: The Supabase CLI may occasionally fail with TLS certificate errors.
Use the Supabase MCP apply_migration tool as a fallback.
3. Seed the Admin User
Section titled “3. Seed the Admin User”RLS requires a user_roles entry before any user can write data. New users who
sign up via Supabase Auth are automatically assigned a viewer role (via the
auto_create_viewer_role trigger), but the first admin must be seeded manually.
- Create a user via Supabase Auth (Dashboard > Authentication > Users > Add User)
- Note the user’s UUID
- Insert the admin role via SQL Editor:
INSERT INTO user_roles (user_id, role)VALUES ('<USER_UUID>', 'admin');4. Configure Taxonomy
Section titled “4. Configure Taxonomy”The taxonomy is DB-driven via taxonomy_domains and taxonomy_subtopics
tables. The application uses TaxonomyProvider (React context) to serve
taxonomy data to the frontend. A hardcoded fallback exists in lib/taxonomy.ts
for the Python pipeline.
-- Example: Insert domains for a bid management clientINSERT INTO taxonomy_domains (name, description, colour, display_order) VALUES ('Technical', 'Technical capabilities and methodologies', '#4A90D9', 0), ('Commercial', 'Pricing, contracts, and commercial terms', '#D4A574', 1), ('Compliance', 'Regulatory compliance and certifications', '#7AB648', 2), ('Case Studies', 'Past project evidence and references', '#9B8EC4', 3), ('Company', 'Company information and credentials', '#E8976C', 4);
-- Insert subtopics under each domainINSERT INTO taxonomy_subtopics (domain_id, name, description, display_order)SELECT d.id, s.name, s.description, s.display_orderFROM taxonomy_domains dCROSS JOIN (VALUES ('Data Security', 'Information security policies and practices', 0), ('Cloud Infrastructure', 'Cloud hosting, platforms, and services', 1), ('Software Development', 'Development methodologies and tools', 2)) AS s(name, description, display_order)WHERE d.name = 'Technical';Also seed the layer_vocabulary table if using content layers:
INSERT INTO layer_vocabulary (name, description, display_order) VALUES ('Fact', 'Verifiable factual claims', 0), ('Evidence', 'Proof, case studies, references', 1), ('Method', 'Processes, methodologies, approaches', 2), ('Policy', 'Rules, guidelines, standards', 3), ('Narrative', 'Persuasive or contextual writing', 4);5. Import Knowledge Base Content
Section titled “5. Import Knowledge Base Content”Q&A pairs from client documents
Section titled “Q&A pairs from client documents”python3 scripts/import_bid_library.py \ .planning/client-documentation/ \ --batch-tag "initial-import"Note: Ensure client .docx files have Track Changes accepted before import.
The import_bid_library.py script uses open_document_safe() from
scripts/docx_utils.py which resolves tracked changes via pandoc.
Website content
Section titled “Website content”python3 scripts/ingest.py https://client-website.comMarkdown files
Section titled “Markdown files”python3 scripts/ingest_markdown.py docs/ \ --tag "internal-docs" \ --author "Client Name"Post-import processing
Section titled “Post-import processing”After import, content is automatically classified, summarised, embedded, and scored. Verify via:
# Semantic search to confirm embeddings workbun run scripts/kb-search.ts "project management" --limit 5
# Batch generate AI summaries for items without onebun run scripts/batch_generate_summaries.ts6. Deploy to Vercel
Section titled “6. Deploy to Vercel”Connect GitHub repository
Section titled “Connect GitHub repository”- Go to vercel.com/new
- Import
ai-solution-hub/knowledge-hubfrom GitHub - Framework: Next.js (auto-detected)
- Build command:
bun run build(configured invercel.json) - Install command:
bun install --frozen-lockfile(configured invercel.json) - Region: London (lhr1) — configured in
vercel.json
Set environment variables
Section titled “Set environment variables”In Vercel Dashboard > Project > Settings > Environment Variables:
| Variable | Value | Notes |
|---|---|---|
NEXT_PUBLIC_SUPABASE_URL | https://<project-id>.supabase.co | From step 1 |
NEXT_PUBLIC_SUPABASE_ANON_KEY | eyJ... | From step 1 |
SUPABASE_URL | https://<project-id>.supabase.co | For Python scripts |
SUPABASE_ANON_KEY | eyJ... | For Python scripts |
SUPABASE_SECRET_KEY | Service role key | For batch scripts and MCP server |
ANTHROPIC_API_KEY | sk-ant-... | Claude API key |
OPENAI_API_KEY | sk-... | OpenAI embeddings (text-embedding-3-large) |
AI_SUMMARY_MODEL | claude-sonnet-4-6 | Optional, defaults to Sonnet |
CRON_SECRET | Random secret | Vercel cron authentication |
NEXT_PUBLIC_SENTRY_DSN | Sentry DSN | Optional — Sentry error tracking |
SENTRY_ORG | Sentry org slug | Optional — required with DSN |
SENTRY_PROJECT | Sentry project slug | Optional — required with DSN |
SENTRY_AUTH_TOKEN | Sentry auth token | Optional — enables source maps |
Deploy
Section titled “Deploy”# Push to main triggers automatic deploymentgit push origin mainOr trigger a manual deployment from the Vercel dashboard.
Vercel cron jobs
Section titled “Vercel cron jobs”The following cron jobs are configured in vercel.json and run automatically:
| Cron | Schedule | Purpose |
|---|---|---|
/api/cron/freshness-transitions | 03:15 daily | Transition content freshness states |
/api/cron/classification-quality | 04:00 Sundays | Audit classification quality |
/api/cron/coverage-alerts | 05:00 Mondays | Alert on coverage gaps |
/api/cron/content-gaps | 05:30 Mondays | Identify content gaps |
/api/cron/quality-score | 05:00 Sundays | Recalculate quality scores |
All times are UTC.
Serverless function timeouts
Section titled “Serverless function timeouts”Key function timeout overrides in vercel.json:
| Function | Max Duration |
|---|---|
| Summary generation | 30s |
| Digest generation | 60s |
| Question extraction, matching, drafting | 120s |
| CopilotKit | 120s |
| Classification quality cron | 120s |
| Quality score cron | 50s |
7. Post-Deployment Verification
Section titled “7. Post-Deployment Verification”Health check
Section titled “Health check”curl https://<your-domain>/api/health# Expected: {"status":"ok","supabase":true,"env":true,"timestamp":"..."}Smoke tests
Section titled “Smoke tests”- Visit the login page — should show Supabase Auth UI
- Log in with the admin user created in step 3
- Dashboard — should show content health strip, active bids, Reorient Me section
- Browse page — should show imported content with quality score badges
- Search — should return semantic results with similarity scores
- Create a test bid — verify the full flow:
- Create bid
- Upload tender document
- Extract questions
- Match KB content
- Draft a response
- Export to Word/Excel
- Q&A Library — should show imported Q&A pairs
- Coverage dashboard — should show domain coverage overview
- Review queue — should show items pending review
- MCP server — verify at
/.well-known/oauth-protected-resource
Security checks
Section titled “Security checks”robots.txtreturnsDisallow: /(verified inpublic/robots.txt)- Security headers present (configured in
vercel.json):X-Content-Type-Options: nosniffX-Frame-Options: DENYStrict-Transport-SecuritywithincludeSubDomains; preloadContent-Security-Policyrestricting scripts, connections, framesReferrer-Policy: strict-origin-when-cross-originPermissions-Policydenying camera, microphone, geolocation, payment
- All non-API routes require authentication (via
proxy.ts) - Public routes:
/login,/auth/callback,/oauth/consent,/.well-known
8. MCP Server Setup
Section titled “8. MCP Server Setup”The MCP server exposes 41 tools, 12 resources, and 5 prompts for Claude Desktop
and Claude.ai integration. See docs/generated/mcp-inventory.md for the
canonical current counts.
- Endpoint:
https://<your-domain>/api/mcp/mcp(Streamable HTTP transport) - Auth: OAuth 2.0 — discovery at
/.well-known/oauth-protected-resource - Plugin: The Knowledge Hub plugin bundle is committed at
lib/mcp/plugin-bundle.ts. Runbun run build:pluginafter changing plugin files, orbun run sync:taxonomyto also refresh the classification prompt and taxonomy snapshot before rebuilding.
MCP Apps (Vite)
Section titled “MCP Apps (Vite)”MCP App UIs live in mcp-apps/ and are built as inline single-file bundles for
deployment:
bun run build:mcp-appsThis generates the app bundles that are served from Vercel.
9. Create Additional Users
Section titled “9. Create Additional Users”For the client pilot, invite users via the admin settings:
- Navigate to
/settings> Team section - Click “Invite User”
- Enter email address
- Assign role (editor for most users, admin for client leads)
The invited user will receive an email with a magic link to set up their
account. New users are auto-assigned a viewer role; admins can upgrade roles
from the Team section.
Roles:
- Viewer: Read-only access to all content
- Editor: Can create/edit content, manage bids, run reviews
- Admin: Full access including team management, taxonomy, governance settings
Monitoring
Section titled “Monitoring”Application health
Section titled “Application health”- Vercel Dashboard: Deployment logs, function logs, function duration metrics
- Sentry: Error tracking, performance monitoring (if configured)
- Vercel Analytics: Page view analytics (via
@vercel/analytics) /api/health: Automated health check endpoint
Database
Section titled “Database”- Supabase Dashboard: Table data, query performance, storage usage
- Connection pooling: Enabled by default on Supabase
- pgvector HNSW indexes: Monitor via
pg_stat_user_indexes - Schema: 30 tables, 92 migrations — see
docs/reference/SCHEMA-QUICK-REFERENCE.md
Cron job monitoring
Section titled “Cron job monitoring”Check Vercel function logs for cron execution. Each cron endpoint validates the
CRON_SECRET header and returns structured JSON responses.
| Service | Plan | Cost | Notes |
|---|---|---|---|
| Vercel | Pro | $20/month | Required for function durations > 10s and cron jobs |
| Supabase | Free | $0/month | 500 MB database, 1 GB storage |
| Anthropic | Pay-per-use | ~$0.20/question | Sonnet for analysis, Opus for complex drafting |
| OpenAI | Pay-per-use | ~$0.01/embedding | text-embedding-3-large (1024-dim via Matryoshka) |
| Sentry | Free | $0/month | Optional — 5K errors/month on free tier |
Estimated pilot cost: $20/month (Vercel) + API usage (variable, ~$5-20/bid depending on question count).