Paperboy is a FastAPI service that generates personalized research digests. It fetches recent arXiv papers (and optionally industry news), ranks and analyzes content with OpenAI models, and produces an HTML digest.
- Docker + Docker Compose
- OpenAI API key
- Supabase project (URL + anon key)
cp config/.env.example config/.envSet at least:
OPENAI_API_KEY=...
API_KEY=...
SUPABASE_URL=...
SUPABASE_KEY=...Notes:
- News fetching is enabled by default. If you want news, set
NEWSAPI_KEY(and optionallyTAVILY_API_KEYfor richer extraction). Otherwise setNEWS_ENABLED=false.
docker-compose up --buildThen open:
- API docs:
http://localhost:8000/docs - Health:
http://localhost:8000/health
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.lightweight.txt
uvicorn src.main:app --reload --host 0.0.0.0 --port 8000Configuration is loaded from config/.env (see config/.env.example).
OPENAI_API_KEY: OpenAI API key (required whenLLM_PROVIDERis unset/openai; not required whenLLM_PROVIDER=fireworks, which usesFIREWORKS_API_KEYinstead — see LLM provider)API_KEY: required for authenticated endpoints viaX-API-KeySUPABASE_URL,SUPABASE_KEY: used for task state + caching (required by the current implementation)
OPENAI_MODEL(default:gpt-4o)NEWS_ENABLED(default:true)NEWSAPI_KEY(required only ifNEWS_ENABLED=trueand you want news results)TAVILY_API_KEY(optional, improves news article extraction)LOGFIRE_TOKEN(optional)SENTRY_DSN(optional): enables backend error reporting to Sentry. Unset = disabled (no-op). No PII is sent —send_default_pii=Falseand user/request contexts are stripped before send. Requiressentry-sdk(declared in requirements); if absent the backend logs a warning and stays disabled.SENTRY_ENVIRONMENT(optional, defaultproduction): environment tag for Sentry eventsWELCOME_FROM_ADDRESS(default:Welcome <hello@paper-boy.app>): verified Resend sender for the signup welcome email sent byPOST /hooks/welcome. RequiresRESEND_API_KEY. Seedocs/welcome-email.md.FEEDBACK_CTA_ENABLED(default:true): show the temporary Tally feedback CTA in newly rendered digest HTML. Setfalseafter the feedback window.FEEDBACK_FORM_URLoverrides the default Tally URL. Seedocs/link-quality-observability.md.ORCHESTRATION_ENABLED(default:false): enables the backend-hosted daily scheduler that replaces n8n. It requiresSUPABASE_SERVICE_ROLE_KEY,RESEND_API_KEY, and the schema indocs/supabase_orchestration.sql. See the backend orchestration rollout guide.
LLM workloads run through an OpenAI-compatible client and default to OpenAI. To run on Fireworks AI instead, set:
LLM_PROVIDER:openai(default) orfireworksLLM_API_MODE(optional):responsesorchat_completions. Unset uses the provider default (responsesfor OpenAI,chat_completionsfor Fireworks).FIREWORKS_API_KEY: required whenLLM_PROVIDER=fireworksFIREWORKS_MODEL(default:accounts/fireworks/models/gpt-oss-120b)FIREWORKS_BASE_URL(default:https://api.fireworks.ai/inference/v1)
OpenAI remains the fallback/default and its behavior is unchanged. See docs/fireworks-migration.md for safe rollout guardrails and what to compare in evals.
Backend orchestration adds protected POST /admin/orchestration/run and
GET /admin/orchestration/status/{source_date} operations. They use the same
X-API-Key authentication as other administrative endpoints and require
ORCHESTRATION_ENABLED=true. See
docs/backend-orchestration.md for request
examples, recovery behavior, and the n8n cutover plan.
All endpoints except basic health/readiness checks require X-API-Key:
curl -H "X-API-Key: $API_KEY" "http://localhost:8000/health"| Endpoint | Method | Auth | Purpose |
|---|---|---|---|
/generate-digest |
POST | Yes | Create a digest (returns task_id) |
/digest-status/{task_id} |
GET | Yes | Poll digest status / result |
/fetch-sources |
POST | Yes | Pre-fetch daily sources for a date |
/fetch-status/{task_id} |
GET | Yes | Poll fetch status |
/preview-new-format/{task_id} |
GET | Yes | Render HTML for a completed task |
/hooks/welcome |
POST | Yes | Send the signup welcome email (Supabase profiles INSERT webhook). See docs/welcome-email.md |
/metrics |
GET | Yes | Metrics + circuit breaker status |
/health |
GET | No | Basic health check |
/ready |
GET | No | Dependency readiness check |
- Docker:
paperboy/Dockerfile,paperboy/docker-compose.yaml - Cloud Run:
paperboy/deploy_cloudrun.sh,paperboy/cloudbuild.yaml
- Architecture:
PROJECT_ARCH.md - Contributing:
CONTRIBUTING.md - AI assistant notes:
CLAUDE.md