Add FastAPI web/API layer and static site
- queries.py: shared read-only query helpers (feed, brief, category counts) returning plain dicts, used by the API and available to the CLI. - api.py: FastAPI service with Pydantic response models (the companion-app contract), CORS, and endpoints for categories, feed, brief, and health; mounts a static site at /. - static/index.html: minimal dependency-free site rendering the daily five and topic/flavor category browsing. - 'goodnews serve' command launches uvicorn (lazy import; core CLI stays pure-stdlib). Web deps live behind the optional [web] extra. - Dockerfile + .dockerignore + build-system metadata so the service installs and deploys cleanly, with the DB mounted as a shared volume. - README: web/API and deployment docs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -64,6 +64,46 @@ For each article, the database stores:
|
||||
- hashes used for dedupe
|
||||
- heuristic scores and reason codes
|
||||
|
||||
## Web / API
|
||||
|
||||
The optional `web` extra adds a FastAPI service and a small static site that
|
||||
consumes it. The same JSON API backs both the website and any future companion
|
||||
app; its auto-generated OpenAPI docs at `/docs` are the shared contract.
|
||||
|
||||
```bash
|
||||
pip install -e '.[web]' # or: .venv/bin/pip install -e '.[web]'
|
||||
python3 -m goodnews serve # http://127.0.0.1:8000
|
||||
python3 -m goodnews serve --host 0.0.0.0 # expose on the network
|
||||
```
|
||||
|
||||
Endpoints:
|
||||
|
||||
- `GET /` — the static site (daily five + topic/flavor browsing)
|
||||
- `GET /healthz` — liveness + scored-article count
|
||||
- `GET /api/categories` — the topic/flavor taxonomy
|
||||
- `GET /api/category-counts` — article counts per topic/flavor
|
||||
- `GET /api/feed?topic=&flavor=&limit=&offset=` — ranked, filtered articles
|
||||
- `GET /api/brief?date=&limit=` — a daily brief (latest if no date)
|
||||
- `GET /api/brief-dates` — available brief dates
|
||||
- `GET /docs` — interactive OpenAPI documentation
|
||||
|
||||
The ingestion CLI stays pure-stdlib; only the `web` extra pulls in FastAPI/uvicorn,
|
||||
so the two halves can be deployed and upgraded independently.
|
||||
|
||||
## Deployment
|
||||
|
||||
The database is never baked into the image — the API and the ingestion CLI share
|
||||
one SQLite file via a mounted volume. Run ingestion (`poll`, `classify`,
|
||||
`build-brief`) on a schedule against the same file.
|
||||
|
||||
```bash
|
||||
docker build -t goodnews .
|
||||
docker run -p 8000:8000 -v /srv/goodnews/data:/data goodnews
|
||||
```
|
||||
|
||||
`GOODNEWS_DB` controls the database path (defaults to `data/goodnews.sqlite3`).
|
||||
Put a reverse proxy (Caddy/nginx) in front for TLS once a domain is attached.
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. Run the poller for a few days and inspect which sources produce useful candidates.
|
||||
|
||||
Reference in New Issue
Block a user