Inspiration
Submitted to Track 5: Community & Gamification.
OneAquaHealth's public data holds one lab campaign per research site, and 95 of the 96 campaigns are from 2023. Between lab visits, the only eyes on these urban streams are the people who live nearby.
The OneAquaHealth Citizen Science App already collects careful stream checks, but nothing tells a volunteer where a check would help most, or why to come back next season. The obvious gamification, points per report, would make it worse: everyone reports the same popular park, the streams scientists know least about stay forgotten, and an alarming report can feel worth more than an honest one.
So we asked: what if points were a price, set by the gaps in OneAquaHealth's own knowledge?
What it does
StreamKeepers prices every stream check by what OneAquaHealth still needs to know: no check this season, old lab data, high health risk, people nearby. Points never depend on what the volunteer finds. A quality check decides whether points are paid, coordinators review what it holds back, and every check is stored in the OneAquaHealth FHIR format.
In Coimbra, Mina Hospital is worth 116 points, and the app shows why, line by line: nobody has checked it this season, its last lab visit was June 2023, its lab health-risk score (0.78) is the highest of the 96 sites, and people live nearby. 2.3 km away, Exploratório is worth 15, because it has already been checked 9 times this season (simulated activity, labelled on screen). Each extra check lowers a site's value, so effort spreads out.
- Missions on a map for 175 sites in the five OneAquaHealth cities (Coimbra, Toulouse, Ghent, Benevento, Oslo), with directions, Street View, calendar reminders and "adopt this stream".
- A guided check in 7 short steps with the same questions and answer codes as the official OneAquaHealth app, in plain words and pictograms, with the official term underneath.
- "What we know about this site", built only from OneAquaHealth lab and land-use data.
- A fair game: a polluted stream earns what a clean one earns. A rushed, far-away or self-contradicting check is held for review, never deleted. Review depends on how a check was made, never on what it reports.
- New streams can be proposed, but earn full points only after a coordinator approves them, so nobody can farm points.
- Coordinators accept or reject held checks with a reason, see coverage by city, and get the list of high-risk streams nobody has reached this season.
- English, Portuguese and French, light and dark, no account; checks wait on the phone when there is no signal.
Who it is for: people who live, walk or play near urban streams, including first-time volunteers; local OneAquaHealth coordinators, who need to know which checks to trust and which streams are missed; and OneAquaHealth researchers and data platforms, who receive checks as OneAquaHealth FHIR indicators with a record of who validated each one.
Expected impact on ecosystems and human health: citizens don't measure pathogens; they keep watch between lab visits, and StreamKeepers decides where that watch goes. Each accepted check becomes OneAquaHealth indicator data on morphology, hydrology, foam, riparian vegetation, land use and invasive organisms, so more streams checked means fewer blind spots for ecosystems. Missions weight streams where the lab found pathogens, faecal indicators and antibiotic-resistance genes near where people (and their dogs) spend time, and coordinators see which of them nobody has reached. In simulation with 10 volunteers per city, unchecked sites fall from 31% to 24% in a season, and high-risk sites checked at least once rise from 71% to 79%, with the same median trip (2.3 km).
How we built it
StreamKeepers is built on three OneAquaHealth tools:
- OneAquaHealth / ENORA public API: sites, lab health risk, land use and the citizen app's official answer codes, snapshotted with SHA-256 so every number can be traced and the app keeps working if the API is down.
- OneAquaHealth FHIR Implementation Guide (HL7 Europe): each check is a FHIR R4 transaction (QuestionnaireResponse with the official codes;
observation-indicators-oahObservations and alocation-oahLocation for accepted checks; Provenance for every review decision). Each resource is read back with a separate request instead of trusting the server's "OK". - Official HL7 FHIR validator: our FHIR output is validated against the IG, with 0 errors and 0 warnings.
We also built a season simulation: an agent-based model on the 106 real research sites, 200 paired runs, using the app's own scoring. Its ablation shows that without OneAquaHealth data the same code still beats classic points, but less on high-risk sites (76% vs 79%): the data decides which forgotten streams come first.
The app is React + TypeScript with Leaflet and MapLibre (3D relief), deployed on Vercel. There is no backend and no account: FHIR is the system of record. 57 automated tests run in CI, and every number in this story comes from a script or results file in the repository.
Challenges we ran into
- The simulation disagreed with our first pitch. Points don't pull volunteers to far-away high-risk streams: their share of checks stays around 24%, even with a triple risk weight. We published it, and built the coordinator's list of unreached streams for what points can't do.
- The OneAquaHealth FHIR sandbox stopped resolving on 23 September 2026. Practice checks were verified on the public HAPI server, labelled as test data; real checks are never sent there.
- The HL7 validator found 5 errors per file on the first run. All fixed and documented in the repo.
- A gap in the IG:
observation-indicators-oahrequiresstatus = final, leaving no place for unreviewed citizen data, so held checks stay QuestionnaireResponses until a reviewer confirms them. - An idea we dropped: predicting lab risk from land use. The signal within a city was close to zero on the 96 public samples, so the claim would not have survived a domain expert.
Accomplishments that we're proud of
- 23% fewer streams left unchecked in a season than with classic points, in a simulation on the real sites, at the same walking distance.
- A scoring rule that cannot reward exaggeration, and a quality check that never penalises a real pollution report (covered by tests).
- FHIR output accepted by the official HL7 validator with 0 errors and 0 warnings, using the same questions and codes as the official OneAquaHealth app, so the data can sit next to the app's own.
- A user test with 5 people: usability score 75 (median), all 5 completed a full check, and nobody felt pushed to exaggerate or rush.
- Evidence that includes what didn't work.
What we learned
- Pricing by coverage does most of the work; the domain data decides the order. The ablation made that visible.
- Geography beats incentives: points spread effort around a volunteer's area, but they don't send people across town. Institutions still have to cover the far high-risk streams.
- Explaining points is harder than computing them. In the user test everyone found the most valuable stream, but nobody could say without a hint why a busy site is worth little. That reason now comes first, in plain words (not re-tested yet). First testers who got no explanation didn't know what to do, so the app now opens with a three-step welcome.
What's next for StreamKeepers
- Connect the coordinator view to the OneAquaHealth FHIR server, with reviewer accounts there.
- Propose a "preliminary citizen data" pathway to the IG authors.
- Run one season with volunteers in one city and compare real coverage with the simulation, to replace assumptions with measurements.
Limits, stated plainly: the simulation is a model (sites and data are real, volunteer behaviour is assumed); mission weights are policy choices, shown in every mission's reasons; the coordinator view reads checks stored on the device in this prototype; the user test is small (5 people aged 19–27, known to the author, remote, in practice mode).
Data: OneAquaHealth project (EU Horizon Europe), public API by ENORA Innovation. FHIR IG: HL7 Europe. Maps © OpenStreetMap contributors, imagery © Esri. A hackathon prototype, not an official OneAquaHealth product. MIT licence.
Built With
- enora-api
- fhir-r4
- fhir-shorthand
- hl7-fhir
- hl7-validator
- leaflet.js
- maplibre-gl
- oneaquahealth-api
- oneaquahealth-fhir-ig
- openstreetmap
- react
- sushi
- typescript
- vercel
- vite
- vitest
Log in or sign up for Devpost to join the conversation.