Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
|
Download docs/ARCHITECTURE.md from VAILL/legislation-tracker: direct link, hf CLI and curl.
- Browser
- Download file 5.53 kB
-
https://huggingface.co/spaces/VAILL/legislation-tracker/resolve/main/docs/ARCHITECTURE.md
- Command line
-
hf download hf://spaces/VAILL/legislation-tracker/docs/ARCHITECTURE.md
-
curl -L -o ARCHITECTURE.md https://huggingface.co/spaces/VAILL/legislation-tracker/resolve/main/docs/ARCHITECTURE.md
5.53 kB
Architecture
High-level
HuggingFace Docker Space (single container, port 7860)
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Browser ββHTTPSβββΆ β Next.js 15 ββ /api/* rewrite βββΆ FastAPI (:8000) β
β (port 7860) β β
β ββ repos/ ββββ β
β supervisord runs: ββ services/ β β
β β frontend (node server.js) ββ routers/ β β
β β backend (uvicorn) β β
β β scheduler (weekly cron) β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββΌββββ
β
HuggingFace Dataset (source of truth)
VAILL/Legislation-Tracker-Data
β
On container start: sync ββββββββ
On pipeline run: upload βββββββββΆ
Components
Frontend β frontend/
- Next.js 15 App Router, TypeScript, Tailwind CSS.
- Each public page has a matching
loading.tsxthat renders skeletons while the server component fetches (Next.js 15 Suspense route conventions). - Client components (Bills table, Calendar, Newsletter, State Spotlight,
USMap) fetch from the browser to
/api/*, which is same-origin β the Next.js rewrite innext.config.tsproxies those to the internal FastAPI port. - Server components use an absolute internal URL (
http://127.0.0.1:8000) because Node'sfetchcan't resolve relative paths.
Backend β backend/app/
- FastAPI, Pydantic v2.
- Layered:
routers/β HTTP endpoints, thin.repositories/β data access. Reads fromdata/*.json(mirrored from the HF Dataset). Designed so a future Postgres swap only touches this layer.services/β external side-effects (hf_sync.py,eu_vectorstore.py).schemas/β Pydantic response models.auth/β file-based bcrypt, JWT sessions.
Pipeline β backend/data_updating_scripts/ + backend/update_data.py
- 14 sequential Python scripts. See PIPELINE.md.
update_data.pyorchestrates: reads args, invokes each step as a subprocess, tracks status indata/pipeline_status.json, uploads back to HF Dataset when done (unless--skip-upload).
Scheduler β backend/scheduler.py
- APScheduler
BlockingScheduleronAmerica/Chicago. - Runs
update_data.py --pull --overwrite-pdf --continue-on-errorevery Monday at 7:00 AM CT. - Only starts inside the Docker container (via supervisord). Local dev does not spawn a scheduler by default.
Request lifecycle
A browser request to https://vaill-legislation-tracker.hf.space:
- HF's edge routes to the Space's container on port 7860 (Next.js).
- If the URL is a page (e.g.
/bills), Next.js renders it β the server component fetches data fromhttp://127.0.0.1:8000/api/*inside the container. - If the URL is
/api/*, the Next.js server rewrite proxies to FastAPI internally. - FastAPI hits the in-memory repository, which was populated from
data/*at startup (which was synced from the HF Dataset). - Response goes back through Next.js β HF edge β browser.
Startup sequence (container boot)
- supervisord launches three programs: backend, frontend, scheduler.
- Backend runs
app.mainon import:- Loads settings from environment (HF Space secrets).
- If
HF_REPO_IDandHUGGINGFACE_HUB_TOKENare set, syncs all core JSONs +weekly_changes/+newsletter_drafts/from the HF Dataset.snapshots/is intentionally excluded (large + only needed at pipeline time). - If
OPENAI_API_KEYis set and no EU vectorstore exists on disk, builds it from the bundledeu-ai-act.pdf(~30s, ~$0.001). - Eagerly loads bills into memory.
- Registers routers and starts serving.
- Frontend runs
node server.json port 7860 (Next.js standalone). - Scheduler stays idle until its cron fires.
Data storage
- HF Dataset β source of truth. Any code path that persists data ultimately writes here. See DATA.md.
- Container disk (
data/) β a cached mirror. Ephemeral on HF; wiped on every container restart and refilled from HF. - Local
.envfiles β dev secrets only. Git-ignored. - HF Space secrets β production values for API keys, HF token, SendGrid, etc. Set in the Space Settings, exposed as environment variables to the container.
Authentication
- Users in
users.json(synced from HF). - Login POSTs
username + passwordto/api/auth/login. Backend bcrypt-checks against the hash and returns a signed JWT. - Frontend stores the token in
localStorage(admin_token) and sends it asAuthorization: Bearer β¦on/api/admin/*requests. - Admin routes gate on
require_adminFastAPI dependency.