This is a submission for the Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass
What I Built
Daily Dose of Nature is an installable, phone-first web app that answers one question: what is worth seeing around me right now, in the time I have? I started it on October 7 for this challenge.
You pick how long you have (a 15-minute break to an afternoon) and where you are. The app works out how far you can walk and back, looks at the season, the time of day and the weather, and gives you one mission: a named park, garden, wood or waterside spot within reach, plus a short list of plants, fungi, birds and other animals that people have actually recorded around there at this time of year. The briefing tells you the direction and distance in plain words, then tells you to put the phone away.
The best spot doesn't have to be where you start. The app looks at everything inside your walking radius and sends you to the reachable place with the strongest observed species. You can find things on the way, too.
It is for people who would like to go outside but have no plan, no energy, or bad weather as an excuse. For now, it covers only Berlin to optimise the data as much as possible.
Demo
Live app: https://dailydoseofnature.onrender.com
Code
Daily Dose of Nature
A phone-first PWA that turns local nature observations into a small, achievable reason to go outside. Missions work without an account or AI model; the app has no backend, analytics, or tracking. Source code is MIT-licensed (see LICENSE).
Hacktoberfest Week 1
Submissions are due October 11 at 11:59 PM PDT (October 12 at 06:59 UTC / 08:59 in Paris). See the official challenge post for submission instructions.
Deploy
Render is a good fit: this is a static Vite PWA, so it needs no application server. Create a Static Site connected to the repository, use build command npm ci && npm run build, and publish directory dist. Render provides HTTPS and can create pull-request previews. A deployed demo is useful for the challenge submission; Render is an option, not a contest requirement.
Run and test
Requires Node.js 20.19+ or 22.12+.
npm install
npm run…MIT licensed. Data and image licences are in the README and in the app's About page.
How I Built It
Data, built once and shipped with the app. A Python pipeline in /pipeline turns open data into a small static pack:
- Species and sightings: 30,850 filtered iNaturalist research-grade observations from a GBIF download (DOI), covering 230 taxa (110 plants, 78 invertebrates, 22 fungi and lichens, 17 birds, and a few mammals and reptiles). It is a download, not a scrape of the API. Only CC0 and CC BY records are accepted.
- Where to go: 7 hand-picked destinations plus about 500 named parks, gardens, woods and waterside spots from OpenStreetMap, merged and de-duplicated by a second script.
- Weather: Open-Meteo forecasts, used for safety rules.
Citizen-science data records where people look, not only where species are. The pack therefore stores aggregate rates per H3 hex cell, shrunk towards a baseline when a cell has few observations, and it flags low-effort cells. It contains no exact occurrence coordinates.
On the phone, everything local. TypeScript, React, Vite and a PWA service worker, with no backend, analytics or account. Mission generation is deterministic:
- Turn your time budget into a walking radius (60% of the outing is walking, with a detour factor).
- Keep only public destinations whose round trip fits the budget.
- Apply safety rules: only street trees in a storm, only lit places on ice or after dark, only shaded spots in heat.
- Among the reachable places, choose the one whose surroundings have the strongest observed species for this season and time of day.
- Rank the species for that place.
Directions without GPS. The briefing gives the compass direction. While the sun is up, SunCalc adds a hint computed on the device, such as "keep the sun on your right". After dark, the hint is dropped.
Open-weight model, optional. An English-only experiment runs SmolLM2-360M-Instruct (Apache-2.0) through WebLLM and WebGPU, entirely on the device. It sees only the season, weather category, time budget and candidate species IDs, never coordinates or place names. Its output is validated against the supplied candidates, and it can't override safety guidance. It is a roughly 200 MB download that starts only when the user taps "Try optional AI mission".
An honest result. In my browser tests the model did not clearly beat the handcrafted briefing. Its objectives didn't adapt reliably to the outing length or add real ecological relationships. So the deterministic mission is the default and the AI stays opt-in, until the data has richer habitat and ecology information. The README says the same.
Privacy by design. Location is requested only when you tap "Use my location", is used in memory for ranking, and is never sent anywhere. The forecast always uses a fixed Berlin-centre point, so no request contains your position. There are no map tiles, and a strict CSP limits what the app may contact. Checklist entries store only a species ID and a date.
Photos and credits. Species photos come from iNaturalist and Wikimedia Commons. They are for non-commercial use only, and each one is credited in the app with its author and licence (CC BY, CC BY-SA, CC BY-NC variants, or public domain). A pipeline script (prepare_species_images.py) rebuilds the credits file from a source table, so a photo can't ship without its attribution. Where I resized a photo, the credit says so.
Testing. 56 unit tests (engine, briefing, data pack), 26 Python pipeline tests, and a Playwright end-to-end test that completes a mission. A regression test covers the "no destination fits this outing" bug, which came from having only 7 destinations: at the default 40 minutes only 1 of 28 start areas had a place in reach. With the OpenStreetMap places, 25 of 28 do.
Known limitations.
- Suggestions summarise past observations. They are not live sightings, calibrated probabilities or guarantees.
- Observer bias is reduced, not removed.
- After dark, or in storm, ice or heat, the choice falls back to the 7 hand-picked places, because the OpenStreetMap ones have no lighting or shade data.
- Added to the iOS Home Screen, location access can be blocked by a platform quirk. The area picker is the workaround.
- Berlin only.
I took it outside
On Sunday evening, I wanted to finish the app first, so I went late, but I made it outside!
With 40 minutes, the app suggested a nearby small park. With a short 10-15 minute break, it put noticing the nature around me ahead of walking somewhere.
It was already dark, so I didn't see any of the species it suggested. I did smell wet leaves on the ground and hear a bird singing, though only briefly.
The app hadn't warned me about the dark, because it only counted "night" an hour after sunset. That's fixed now, and it shows a safety note as soon as part of the outing is after dark.
Why Does Open Innovation Matter?
- Your location stays yours. A cloud API would need your position to give a local answer. Here the ranking runs on the phone, and you can check that in the open code.
- It costs nothing to run. It is a static site with no server, key or per-request bill. Open data (GBIF/iNaturalist, OpenStreetMap, Open-Meteo, SunCalc) feeds it, and the sources are credited in the app.
- Open data made the fix possible. When the app kept saying "no destination fits", OpenStreetMap's open licence let me add about 500 real places in one afternoon, and coverage went from 1 of 28 start areas to 25 of 28.
- The model is swappable and optional. The app works without it. Because the weights are open, I could pin an exact revision, check its licence, run it on the device and judge it against the baseline. That is how I found it didn't help yet.
- Anyone can rebuild it. The pipeline can be pointed at another city, and every recommendation can be traced to the data.
Prize Categories
-
Best Use of Render: the live app at https://dailydoseofnature.onrender.com is a Render Static Site. Render builds it with
npm ci && npm run buildand serves the PWA and its data pack over HTTPS, so the app needs no server of its own. - Best Use of GitHub Copilot: I built this project with the GitHub Copilot agent in VS Code, in a chat session working directly in the repo. One example: when users kept seeing "no destination fits this outing", Copilot checked the real data and found that only 1 of 28 start areas had a destination in reach at the default 40 minutes, because the app knew just 7 places. It wrote a pipeline that pulled about 500 named parks, woods and waterside spots from OpenStreetMap, then added a regression test. Coverage went to 25 of 28 areas. Copilot also helped add the on-device sun-direction hint, and it kept the 56 unit tests, the Python tests and the end-to-end test green as I changed things.
Top comments (0)