DEV Community

Manwitha Gopal Sunkari
Manwitha Gopal Sunkari

Posted on

FieldCast: a weather window finder that prints a pocket field zine

Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass Submission 🌿

This is a submission for the Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass

What I Built

I sit at a screen most of the day. When I try to take a walk break, three things stop me:

  • I don't know if the weather is good right now.
  • A walk with no goal feels pointless.
  • Nature apps want my phone in my hand the whole time.

FieldCast is my answer.

  • You pick a place. It reads the weather and sorts conditions into four walk types: bird chorus, pollinators, post-rain emergence, and high-UV shade.
  • Then it formats a one-page pocket zine that you print and fold. It has a sensory prompt, a short reflection, and three things to look for.
  • The screen is the short part: check, print, go. The goal is to leave the phone at your desk.

It is for people who work at screens and want a reason to step outside.

Demo

What the live page really does. GitHub Pages cannot run Python, so the live page runs no AI model:

  • It uses a client-side JavaScript copy of my threshold rules for the current hour only. There is no 24-hour timeline and no "best time" computed in the live demo.
  • The zine text and the three species bounties are written regional presets.
  • The nearby-species panel calls the live iNaturalist Open API from your browser.
  • The spectrogram is a decorative canvas animation with an optional microphone frequency visualizer. It does not identify species.
  • Client-side extras (all confirmed working):
    • Calendar (.ics) export: downloads an iCalendar file to block 30 minutes of walk time on your calendar.
    • Streak counter: tracks consecutive days outside via localStorage.
    • Field logbook: saves your offline walk reflections in localStorage.
    • QR links: encodes iNaturalist species search URLs so you can look them up later (requires internet when scanned).

What runs only locally. The Python backend runs TabPFN v2 and Gemma 2B. That is the open-source AI in this project, and the local CLI / server demonstrates both.

How I Built It

TabPFN v2 sorts weather into walk types.

  • It reads a CSV I wrote by hand: 32 rows, 8 per walk type (data/trail_observations.csv). I defined the state labels with my own thresholds. They are synthetic references, not a published dataset or verified wildlife sightings.
  • It estimates which weather favors each walk type. It does not predict wildlife occurrence.
  • Air quality (AQI) is a manual form field with a placeholder. Open-Meteo's standard weather endpoint does not return it without a separate call.
  • The API response includes an engine_used field (tabpfn_v2 vs fallback_random_forest), proving the real model answered and not a fallback.

Gemma 2B (gemma2:2b via Ollama) writes three things: the zine title, a sensory line, and a reflection prompt.

Two things went wrong during development, and I'm sharing them because they shaped the final design:

  • My first test zine generated a reflection asking about "the async race condition in the Avian Chorus." The cause was my own HTML form: its default placeholder text was "Debugging an async race condition & need an eyes-up reset." Gemma picked that up and generated debugging analogies. I rewrote the prompt and default text specifically for natural history. Three sequential runs after that were completely on-topic (e.g., "Deccan Canopy Oasis"). They are simple, but grounded in nature.
  • Gemma also hallucinated species when asked to invent bounties. One bounty was "Nest Material," and a frog call was labeled "Regional Call." A 2B parameter model shouldn't be trusted for field taxonomy. As a result, the three species to find are curated presets, not generated by Gemma.

Other parts. FastAPI, Open-Meteo for weather, iNaturalist for nearby sightings, Leaflet for the interactive map, and pure CSS @media print rules for the 1-page foldable zine layout.

Dead end. I planned to stream bird calls from xeno-canto. When I tested their v2 API, the endpoint returned "no longer available." I removed the button instead of faking it.

AI agent. I built this with an AI coding agent (Google Antigravity). Its early reports claimed conclusions it had not verified, like an agreement rate with no source file. I stopped it and required raw terminal outputs and saved artifact files in outputs/ for every claim in this post.

What I Measured

I benchmarked the JavaScript threshold rules (extracted from index.html and executed in Node) against TabPFN v2 on the same real 24-hour Hyderabad Open-Meteo forecast (outputs/comparison_local_hour.csv).

  • The top predicted state differed in 5 of 24 hours.
  • While 19 hours agreed, 11 of those were night hours (19:00 to 05:00). My training rows only cover daytime conditions (06:00 to 18:00). Both methods default to calling those night hours "bird chorus." Within the 13 in-distribution hours, 5 differed (38.5% disagreement).
  • Example at 13:00 IST: Weather was 33.4°C, 30% humidity, 10.9 km/h wind, and UV index 7.7. The rule said Pollinators because its rigid threshold requires UV ≥ 8.0 or Temp ≥ 34.0. TabPFN smoothed the boundary and predicted High-UV Shade Walk (58.0% probability) over Pollinators (30.1%).
  • Pressure anomaly: Hyderabad's surface pressure (~956 hPa) is far below my training CSV range (1002 to 1016 hPa). I tested both surface pressure and mean sea-level pressure (pressure_msl, ~1013 hPa). The top state changed in 0 of 24 hours, but TabPFN's confidence changed dramatically. On unseen night hours, its confidence jumped from 45–49% (surface pressure) to 77–86% (sea-level pressure).
  • On one in-range test input, TabPFN output 100% / 0% / 0% / 0%. With only 32 training rows, high confidence does not equal empirical accuracy.
  • Inference latency on CPU:
    • TabPFN v2: 68.2 s cold start (model load + torch weights initialization), 4.83 s warm.
    • Gemma 2B: 34.1 s cold start, 9.97 s warm.
  • The backend's best_window_today tests 6 synthetic hour offsets against current conditions. It is not a weather forecast, and the UI explicitly labels it as such.
  • I have not validated either method against real bird surveys, so I make no claim about which is biologically more accurate.

Why Does Open Innovation Matter?

  • I could look inside. Because TabPFN ran locally, I could inspect feature values, compare it side-by-side against my JavaScript rules, and discover the pressure distribution mismatch. A proprietary cloud endpoint would have hidden this behavior behind an API call.
  • Zero per-call cost. Both Gemma and TabPFN ran entirely on my CPU. Generating field guides and sorting weather requires no API keys, credit cards, or rate limits.
  • Swappable. The LLM backend is an Ollama parameter in the UI. Anyone can test the prompt against Llama 3.2 or Mistral without rewriting the application.
  • Where open had trade-offs. Gemma 2B is prone to hallucinations on factual taxonomy. The 68-second cold start on a CPU is also steep when you just want to step outside immediately.
  • Current limit. The app still relies on third-party APIs for weather (Open-Meteo), species (iNaturalist), map tiles, and QR code rendering. It is not a completely offline tool.

How It Went Outside

I printed the Deccan Urban Canopy zine at 17:15 IST on October 11 and took a 25-minute loop around the neighborhood park without my phone.

  • Conditions: 31°C, light wind, long late-afternoon shadows.
  • What worked: The folded 1-page format fits in a shirt pocket without creasing into a mess. Spotting the bounties was surprisingly practical: I found copper pods hanging from roadside Peltophorum trees, crushed a fallen Neem leaflet to smell the sharp herbal scent, and spotted a White-throated Kingfisher perched silently on a low overhead wire near the park boundary.
  • What didn't work: The sensory prompt advised listening for high-frequency bird harmonics. Two blocks away from the avenue, traffic noise from auto-rickshaws and scooters completely masked subtle canopy sounds. The zine works best when you actually step off the road and into interior garden trails.
  • The takeaway: Leaving the phone on the desk broke the subconscious habit of checking notifications at red lights or trail benches. Having a paper prompt with three specific things to notice turned a vague break into an intentional reset.

What's Next

  • Flag night hours as "not an active window" instead of extrapolating the model outside its training hours.
  • Calibrate the training set against real eBird and iNaturalist observation timestamps.
  • Add an hourly breakdown in the static demo comparing rules and TabPFN side by side.

Prize Categories

  • Best Use of TabPFN: Classifies hourly micro-climate features using Prior Labs TabPFN v2 locally on CPU, with a documented 24-hour benchmark against deterministic rules.
  • Best Use of Gemma: Uses local gemma2:2b via Ollama to compose nature zines with strict JSON formatting and reproducible test logs.

Top comments (1)

Collapse
 
launchgatecheck profile image
Launch Gate •

The night-hour breakdown is much more useful than the headline 19/24 agreement. Since the output leaves the screen as paper, I'd put the same limits on the zine itself: location, local forecast time, generated-at time, and whether it came from static rules or the local model. A print fixture at 18:55 with a 30-minute walk would catch a daytime recommendation crossing into the unsupported night hours. Another is a previously generated zine after the weather request fails: keep the last-good timestamp visible instead of making the printed advice look current. That would preserve the careful caveats in this post where someone actually uses the recommendation.