Deployment Guide
Deploy the web app on its own or pair it with the optional Python backend for analytics and recommendations.
Source: apps/web/content/docs/guides/deployment.mdx
AI Web Feeds supports two practical deployment profiles.
Choose a Deployment Profile
| Profile | What runs | When to use it |
|---|---|---|
| Web only | Next.js web app | Default choice for the reader, compact dashboard, docs, and OPML export |
| Web + backend | Next.js web app plus ai_web_feeds.web_api | Use when you need backend-backed analytics APIs |
Web-Only Deployment
The web-only setup is enough for most of the public product.
It supports:
//dashboard/api/exports/opml/docs/llms.txtand/llms-full.txt
Build and run the web app
cd apps/web
pnpm install
pnpm build
pnpm startShared Runtime Preparation
Even in the web-only profile, the standalone app expects generated data artifacts.
1. Create Environment File
cp .env.example .env2. Configure Environment Variables
For the OAuth-protected admin observability flow, this is the minimum local setup:
# pragma: allowlist secret - documentation placeholder
DATABASE_URL=postgresql://user:pass@host.neon.tech/db?sslmode=require
BETTER_AUTH_SECRET=replace-with-a-long-random-secret
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
GITHUB_CLIENT_ID=your-github-client-id
GITHUB_CLIENT_SECRET=your-github-client-secretOptional local overrides:
AIWF_TELEMETRY_DIR=../../data/telemetry
# AIWF_TELEMETRY_SALT=replace-with-a-stable-hashing-salt
# BACKEND_URL=http://127.0.0.1:8001Admin access uses Google or GitHub OAuth. Only pre-authorized accounts (with role = 'admin') are granted access.
BACKEND_URL is optional. It is only required if you want live backend-backed analytics APIs. Without it:
/,/dashboard, and/docsstill work/analyticsand advanced analytics pages are not public routes/recommendationsis not a public route
Docker Compose
The repository ships a two-service compose setup that matches the codebase as it exists today:
web: the standalone Next.js application on port3000monitor: the Python monitoring/WebSocket service on port8000
Start both services with:
docker compose up --buildNotes:
- The compose stack no longer assumes a separate nginx container or a generic Python HTTP backend that the repository does not currently assemble.
BACKEND_URLremains optional. Set it only if you are running the separate ai-web-feeds backend HTTP surface for analytics APIs.NEXT_PUBLIC_WEBSOCKET_URLis optional. Local development defaults tohttp://localhost:8000; deployed environments default to same-origin WebSocket connections unless you set this variable to an explicit monitor/WebSocket URL.- The monitor service uses the default SQLite database at
sqlite:///data/ai-web-feeds.dbunless you overrideDATABASE_URL.
Shared Python Runtime Setup
The standalone web app expects two things for the full reader and search experience:
- the checked-in source catalog under
data/ - a generated article corpus at
data/articles.generated.json
You do not need a Python HTTP backend for /, /api/articles, or GET-based search. You do need the Python runtime when you want to poll feeds and rebuild the corpus artifact.
1. Install Dependencies
uv syncBuild the article library
uv run ai-web-feeds corpus refreshThat command populates runtime data and writes data/articles.generated.json for the web app.
Optional Backend Deployment
Add the backend only when you need live server-backed features.
Start the backend
uv run uvicorn ai_web_feeds.web_api:app --host 127.0.0.1 --port 8001Point the web app at it
BACKEND_URL=http://127.0.0.1:8001With BACKEND_URL configured, the web app can enable:
- analytics summaries and exports
- write-side analytics logging
Environment Notes
Common variables:
# pragma: allowlist secret - documentation placeholder
DATABASE_URL=postgresql://user:pass@host.neon.tech/db?sslmode=require
BETTER_AUTH_SECRET=replace-with-a-long-random-secret
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
GITHUB_CLIENT_ID=your-github-client-id
GITHUB_CLIENT_SECRET=your-github-client-secret
# BACKEND_URL=http://127.0.0.1:8001Verification Checklist
- the web app builds with
pnpm build data/articles.generated.jsonexists and is current- the public routes load without a backend
- if
BACKEND_URLis set,/api/analytics/*and/api/recommendationsproxy to the backend