Sportfish reporting QA workflow demo — data intake, validation, structured export (public-data-safe).
The on-screen product name in the demo UI remains Reporting and Tagging Intelligence Portal so screenshots and screen recordings stay consistent.
- Public-data-safe: Synthetic demo data only—see
docs/data-provenance.md. - No internal HRI/CSSC data: This repository does not use confidential, restricted, or internal datasets from HRI, CSSC, or partner fishery programs.
- Prototype: Not biological inference, stock assessment, or management-grade output—see Honest limits at the end of this README.
End-to-end UI built with FastAPI + SQLite + static HTML (uvicorn api.main:app). Demo uses synthetic data only.
Full portal walkthrough (assets/gif/portal-end-to-end.gif).
Expand: 6 dashboard screenshots (home → submit → contributions → QA → exports → access banner)
| Screen | Preview |
|---|---|
| Home / overview | ![]() |
| Submit trip flow | ![]() |
| My contributions (map + timeline) | ![]() |
| QA analyst queue | ![]() |
| Analyst exports | ![]() |
| Access / role banner | ![]() |
Source recording: assets/Source/portal-demo.mp4
Regenerating GIFs / ffmpeg: docs/artifact-finalization.md
If you skim GitHub repos fast, here is the point of this one:
| Question | Answer |
|---|---|
| What problem does it solve? | Messy volunteer reports slow teams down—this prototype standardizes intake and highlights likely issues early. |
| What did you build? | A working web demo with reporting forms, QA queue, downloads, and a participant summary view (fake data). |
| How do you prove it quickly? | GIF + screenshots above + setup steps below. |
Printable one-pager (three panels): open docs/reviewer-one-pager.html in a browser → Print → Save as PDF.
- Fewer messy records: coordinates, counts, dates, and duplicates get flagged automatically.
- Faster reviews: QA items show up in a queue with actions (review / escalate / dismiss).
- Better reporting: downloads are ready as CSV or GeoJSON.
- Clear participant view: totals, a simple map footprint, timelines, and tag histories.
This demo uses fake data only. It is not measuring fish populations or predicting outcomes.
- Workflow prototyping: Demonstrates intake → validation → QA queue → structured export using repeatable synthetic seeds (
api/seed_data.py). - Handoff examples: CSV and GeoJSON export routes show how reviewable tabular and spatial packages could look—without claiming real-world catch statistics.
Some checks can sound "smart," but they only suggest issues for a human to confirm. Nothing here replaces expert review.
| Area | What you see |
|---|---|
| Home / overview | Entry point and navigation to the flows below |
| Submit Trip | Forms for trip, catches, optional tag report; success/error messages |
| My Contributions | Trip totals, KPI cards, simple map dots, timeline list |
| Analyst Queue | Flag list, severity, scores, actions |
| Analyst record | Drill-in view for a flagged record (/analyst/record/{type}/{id}) |
| Analyst Exports | Download CSV / GeoJSON, QA summary JSON |
| Recapture timeline | Ordered events for a tag code |
- Backend: FastAPI + SQLite (
api/main.py,api/db.py,api/qa.py) - Frontend: simple HTML pages (
frontend/*.html) - Demo data: generated by
api/seed_data.py
flowchart LR
Reporter[Reporter] --> IntakeAPI[IntakeAPI]
IntakeAPI --> QaEngine[QaChecks]
QaEngine --> AnalystQueue[StaffQueue]
QaEngine --> ExportLayer[Downloads]
QaEngine --> ParticipantView[ContributionView]
Run these commands from the repository root (the folder that contains api/ and frontend/).
-
Install Python packages:
python3 -m pip install -r api/requirements.txt
-
Load demo database + CSV seeds:
python3 api/seed_data.py
-
Start the server:
uvicorn api.main:app --reload --app-dir . -
Open:
http://127.0.0.1:8000/
/— home/submit-trip/my-contributions/analyst/queue(requires analyst role; see below)/analyst/exports(requires analyst role)/analyst/record/{record_type}/{record_id}(requires analyst role)/recaptures/{tag_code}
Role: use the Role dropdown in the top bar (angler vs analyst). That sets ?role=analyst in the URL (and a stored preference) so analyst pages load correctly. For direct API calls, you can send the header x-role: analyst on analyst-only endpoints.
Intake & read (no special role)
POST /api/v1/tripsPOST /api/v1/catchesPOST /api/v1/tag-reportsGET /api/v1/trips/{trip_id}GET /api/v1/trips/{trip_id}/layers— map/timeline layers for contributions view (optional filters:species,includeFlags,includeTags)GET /api/v1/tag-reports/{tag_code}/history
Demo helpers
GET /api/v1/demo/ids— sample IDs for a quick UI walkthrough
Analyst role (x-role: analyst or ?role=analyst where applicable)
POST /api/v1/qa/runGET /api/v1/qa/flagsPATCH /api/v1/qa/flags/{flag_id}GET /api/v1/records/{record_type}/{record_id}GET /api/v1/exports/reports.csvGET /api/v1/exports/reports.geojsonGET /api/v1/exports/qa-summary.json
See docs/data-provenance.md for what "fake data" means here.
Running python3 api/seed_data.py fills data/mock/ with repeatable sample trips, catches, tags, plus a SQLite file for local runs.
| Output | Notes |
|---|---|
| CSV | GET /api/v1/exports/reports.csv (analyst role) — tabular review package |
| GeoJSON | GET /api/v1/exports/reports.geojson (analyst role) — map-friendly features |
| QA summary JSON | GET /api/v1/exports/qa-summary.json (analyst role) |
| Local DB | data/mock/portal.db — created when you run api/seed_data.py |
Use the Analyst role in the UI (or x-role: analyst on API calls) to access export endpoints.
This is a demo for showing how intake + checks + downloads could work together. Do not use it as proof about real-world fish numbers or rules.






