This is a submission for the Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass
"Go touch grass," they said.
Every developer loves joking about touching grass right up until we actually have to step away from our dual monitors and mechanical keyboards.
When this week's Hacktoberfest challenge dropped with the theme "Touch Grass", my first reaction was: alright, how do I build something that genuinely gets people outside without turning into another screen-time trap?
Because here's the thing about most "outdoor" apps: they want your eyeballs the entire time you're outside. You're supposed to look down at your screen, track your pace, check your notifications, and fiddle with settings while walking past actual trees.
Worse yet, the moment you get to a real trailheadβthe kind where you can't hear traffic anymoreβyour phone signal drops to zero bars. And when you open any modern cloud AI assistant to ask about trail conditions or elevation gain:
[!] Network Error: Unable to reach server. Please check your connection.
Your \$1,000 phone is suddenly a paperweight, and the cloud AI you relied on is completely useless.
So I spent this week building GrassMapper.
What is GrassMapper?
GrassMapper is an offline-first trail companion and outdoor habit OS powered by Google's open-weight Gemma 3 model running 100% locally on your machine via Ollama.
It has one core rule: The screen should be the shortest part of your day.
You open it, pick where you want to wander, hit "Pocket Audio Briefing", shove your phone or laptop in your backpack, and go outside. It talks to you through your earbuds while you lace your hiking boots, gives you the trail rundown, and leaves you alone to enjoy the walk.
And because it's built for real people with different setups, it works two ways:
- A cute web dashboard running on Flask with interactive Leaflet maps, audio, and live streaming tokens.
-
A terminal CLI for when you just want to run
grassmapper planin your shell and get right to the point.
The Fun Stuff (Features I Actually Enjoyed Building)
π¦ 1. Sprout the Fox (Your Trail Mascot)
Let's be honest: productivity gamification can be pretty annoying. But I couldn't resist giving this project a mascot.
Meet Sprout π¦. She floats in the corner of your dashboard, keeping an eye on your outdoor habits. When you log a walk, identify a plant, or tick off a daily nature quest, she showers the screen with confetti and plays a little 8-bit celebration chime.
The fun engineering detail? Zero audio files or sound CDNs. The chime is synthesized in real time using the browser's Web Audio APIβthree oscillators (triangle wave for warmth, sine for sustain, and a snappy attack envelope) vibrating straight out of your browser's audio context. Totally offline, 0 KB download.
π± 2. Grass Points (GP)
You earn Grass Points for real-world outdoor acts:
- Logging a hike (+15 GP)
- Identifying a bird or plant (+10 GP)
- Keeping an outdoor streak alive (+25 GP)
You level up from Seedling π± (0 GP) β Trail Scout π₯Ύ (50 GP) β Forest Ranger π² (200 GP) β Peak Bagger β°οΈ (500 GP).
It sounds silly, but seeing your little level progress bar move because you actually went for a 30-minute walk around the neighborhood is surprisingly satisfying.
πΊοΈ 3. The OpenStreetMap Trail Radar
I didn't want Google Maps tracking anyone or hitting an API billing threshold.
GrassMapper uses Leaflet.js with OpenStreetMap tiles. It renders your trail as an animated polyline with custom pins for the trailhead π, water/vista points π§, and wildlife hotspots π¦ .
You can change locations three ways:
- Search bar: Checks an offline dictionary of 21 famous national parks, peaks, and trails first (so search works with zero internet!), then gracefully falls back to OSM Nominatim if you're online.
- Click-to-place: Click anywhere on the map, and the route re-centers right there.
- GPS button: One tap pulls your actual coordinates via browser geolocation.
π± 4. It works straight from your phone
You don't need a native app store download. If your laptop is running GrassMapper on your home Wi-Fi (or a mobile hotspot at a campsite), you just open http://YOUR_LOCAL_IP:5000 on your phone's browser. I tuned the meta tags and viewport so it feels like a native full-screen app.
The Technical Stuff I Worked Around
The Gemma 3 Tool-Calling
When I started, my plan was classic agentic AI: give Gemma 3 a SerpApi search tool via Ollama so it could look up trail conditions autonomously whenever it needed to.
Then I ran it:
ollama._types.ResponseError: registry.ollama.ai/library/gemma3 does not support tools (status code: 400)
Turns out, the current Ollama build for Gemma 3 throws an immediate HTTP 400 if you pass a tools= list.
My initial thought was to downgrade to another model. But I really wanted Gemma 3βGoogle's open weights are incredibly snappy and have surprisingly rich botanical and geographical knowledge for their size.
So instead of tool-calling loops, I built a pre-inference grounding pipeline in Python:
[ User Input: "Kedarkantha Trek, moderate" ]
β
βΌ
Is SERPAPI_KEY available & online?
βββ YES βββΊ Search SerpApi for recent trail reports & weather
β Inject results into system prompt as [GROUNDING]
βββ NO βββΊ Skip quietly (graceful offline fallback)
β
βΌ
Stream Gemma 3 locally via simple_stream()
β
βΌ
Token-by-token SSE stream directly to browser
It ended up being way better than native tool calling:
- Zero latency wasted on the model deciding whether to call a tool.
- Zero tool-call hallucination or format errors.
- When you're offline in the woods, it just skips SerpApi without a hitch and lets Gemma 3 run pure local inference.
Architecture: Zero Cloud Lock-In
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Web Dashboard / Phone / CLI β
β Leaflet Map β’ Web Audio β’ Audio Briefing β
ββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββ
β
ββββββββββββββββββββββββββββΌββββββββββββββββββββββββββββββ
β Flask Server (SSE Streaming) β
β Token-by-token output with 0 WebSockets β
ββββββββββββββββ¬βββββββββββββββββββββββββββ¬βββββββββββββββ
β β
ββββββββββββββββΌββββββββββββββ ββββββββββΌβββββββββββββββ
β Ollama Engine (Local) β β SerpApi Grounding β
β Gemma 3 Open Weights β β (Optional, live data) β
ββββββββββββββββ¬ββββββββββββββ ββββββββββ¬βββββββββββββββ
β β
βββββββββββββ¬βββββββββββββββ
β
ββββββββββββββββββββββββββββΌββββββββββββββββββββββββββββββ
β SQLite (~/.grassmapper.db) β’ Sentry Agent Tracing β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Everything that mattersβyour journal, hike logs, sightings, habit streaksβis stored in a local SQLite file in your home directory (~/.grassmapper.db). No telemetry, no account creation, no analytics tracking where you walk.
π Hacktoberfest Prize Alignment
Here is how GrassMapper addresses the challenge prize categories:
π Best Use of Gemma ($200)
Gemma 3 is the primary intelligence here. It powers:
- Trail Architect: Custom itineraries with gear checklists, elevation notes, and difficulty ratings.
- Naturalist Guide: Explaining wildlife sightings, botany facts, and seasonal changes.
- Trail Debriefs: Reflecting on your journal entries and encouraging healthy outdoor habits. All running locally via open weights, zero closed API reliance.
π Best Use of Render ($200)
GrassMapper comes with a production-ready render.yaml Blueprint and requirements.txt. With one click, an outdoor club, scout troop, or university hiking group can host a shared community instance of GrassMapper on Render backed by Gunicorn.
π Best Use of SerpApi ($100)
AI models have knowledge cutoffs. Trails have seasonal mud seasons, flash flood warnings, and bridge closures. When internet is available, SerpApi grounds Gemma 3 with live trail reports and weather data right before generation runs.
π Best Use of Sentry Agent Tracing ($100)
Every single AI interaction is wrapped with sentry_sdk:
-
op="ai.inference"traces Ollama token generation time and model latency. -
op="tool.search"traces SerpApi roundtrips. You get crystal-clear flame graphs showing exactly where your time went during every trail plan generation.
Try It in 2 Minutes
1. Make sure you have Ollama & Gemma 3
# From https://ollama.com
ollama pull gemma3
2. Clone & Install
git clone https://github.com/your-username/grassmapper.git
cd grassmapper
pip install -r requirements.txt
3. (Optional) Add your API keys in .env
SERPAPI_KEY=your_key_here
SENTRY_DSN=your_dsn_here
(Both are optional! It works completely fine offline without them.)
4. Fire it up!
To open the Web Dashboard:
python app.py
Open http://localhost:5000 (or http://YOUR_LOCAL_IP:5000 on your phone).
Or stay in the terminal:
python grassmapper.py plan # Generate a trail plan
python grassmapper.py log # Log a finished hike
python grassmapper.py observe # ID a wildflower or bird
python grassmapper.py stats # Check your Grass Points & streak
Closing Thoughts
We build so much software that tries to capture attention and hold it hostage inside a browser tab.
Building GrassMapper was a breath of fresh airβliterally. It was fun to build an AI app where the definition of success isn't "how many minutes did the user spend on this page?", but "did the user shut their laptop and step outside?"
If you've been glued to your IDE all day: save your files, run python grassmapper.py plan, and go touch some grass. You've earned it. πΏπ₯Ύ
AI Disclosure
This project utilizes Google's open-weight Gemma 3 model running locally via Ollama to generate offline trail itineraries, nature observations, and outdoor journaling reflections. AI assistance was also used during development for drafting documentation, structuring test cases, and writing code. All core application logic, database schemas, web endpoints, and Leaflet map integrations were implemented, tested, and verified with combined efforts of me and my coding buddies (bunch of AI coding tools an software).
Source Code: github.com/VaishnaviOnPC/grassmapper
Built with: Python, Flask, Gemma 3, Ollama, Leaflet.js, SerpApi, Sentry, Render
License: MIT






Top comments (0)