--- title: Scouting · Racing Santander emoji: ⚽ colorFrom: blue colorTo: indigo sdk: docker app_port: 7860 pinned: true --- # Scouting · Racing Santander FastAPI + DuckDB scouting dashboard. Reuses the visual design of the static HTML report but loads data from a Hugging Face Dataset and recomputes scoring on the server. ## Required Space secrets Set these in **Settings → Repository secrets** of the Space: | Secret | Required | Purpose | |---|---|---| | `APP_PASSWORD` | yes | Shared password for the login gate | | `SESSION_SECRET` | yes | Random string used to sign auth cookies | | `DATASET_REPO_ID` | yes | HF dataset repo id, e.g. `racing-tools/scouting-data` | | `HF_TOKEN` | yes if dataset is private | Read-scope token for the dataset repo | | `DATA_MAX_AGE_HOURS` | no | Cache TTL before re-pulling the dataset (default 24) | ## Local development ```bash cd scouting # 1. produce parquets locally (one-time / on refresh) python ingest_azure.py python build_player_season.py python enrich_attrs.py python enrich_tm.py --skip-extra --limit 100 # 2. point app to the local data dir and run export DATA_DIR=$(pwd)/data/clean cd app && uvicorn main:app --reload --port 7860 ``` Open http://localhost:7860/ — no `APP_PASSWORD` set means dev-mode (any password is accepted on the login form, or skip if env unset). ## Refreshing data without a Docker rebuild ```bash HF_TOKEN=hf_xxx python scripts/push_to_hf_dataset.py ``` Then restart the Space (Settings → Factory rebuild) — the next boot pulls the new parquets via `huggingface_hub.snapshot_download`. ## Architecture - `app/main.py` — FastAPI app, mounts static, registers routes - `app/data.py` — DuckDB on parquet, registers `base` view joining player_season + tm_enrichment - `app/scoring.py` — wraps `scouting_score.py` for in-memory scoring with custom weights - `app/auth.py` — signed-cookie shared-password gate - `app/routes/` — meta / score / player / best11 endpoints - `app/static/` — extracted HTML, CSS, JS from `generate_report.py` with `fetch()` calls ## API quick reference - `GET /api/meta` — seasons, leagues, positions, blocks - `POST /api/score` — filtered + scored player-season rows - `GET /api/player/{playerId}?season=24-25` — full detail - `POST /api/best11` — top-1 per pitch slot - `POST /api/login` — set auth cookie - `GET /api/auth-status` — whether the current session is authenticated - `GET /healthz` — bypasses auth, returns row counts