This is a submission for the Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass.
Trailhead
A local-first Streamlit app that uses an open-weight LLM to turn a few taps into a short outdoor outing, then gets you off the screen.
What it does
- Pick your outing — Activity (walk, run, hike, birding, nature observation, photography), time (15 min – 3 hrs), and location (city name or lat/lon)
- Get conditions — Fetches live weather, sunrise/sunset, and daylight remaining from Open-Meteo (free, no API key)
-
Generate a card — A locally running open-weight model (Gemma 3 4B via Ollama) creates an "outing card" with
- A general route suggestion (no fake map data)
- What to look and listen for this week at your latitude and season
- 3 "off-screen challenges" (e.g., "Sit silently 3 minutes and count the sounds you hear")
- A one-line safety note based on actual weather and daylight
- Go outside — Download the card as HTML or PDF, or tap "Take me outside" for…
What I Built
Trailhead is a local-first Streamlit app that turns a few taps into a short outdoor outing — and then deliberately gets out of your way.
You pick three things: an activity (walk, run, hike, birding, nature observation, photography), how much time you have (15 min to 3 hours), and where you are (a city name, or raw lat/lon). Trailhead pulls the live weather and remaining daylight from Open-Meteo, then asks a locally running open-weight model — Gemma 3 4B via Ollama — for an "outing card":
- A route suggestion in plain language ("loop through the nearest green space, turn around at the halfway mark") — deliberately no invented trail names and no fake map data.
- Seasonal highlights for this week at this latitude: what to look and listen for right now.
- Three off-screen challenges — concrete, phone-free things to do, like "sit silently for three minutes and count every distinct sound you hear."
- A one-line safety note grounded in the actual conditions ("dark in 40 min — bring a headlight or turn around by 6:20pm").
Then it tries to make the screen the shortest part of the experience. Download the card as a self-contained HTML file or a PDF and print it. Or hit "Take me outside", which replaces the whole UI with a single line — "See you in 42 minutes" — and a return time. When you get back, you jot down 1–3 notes. Everything is stored locally in SQLite, and past cards stay readable offline.
Who it's for: anyone who wants a reason to step outside but doesn't want to spend twenty minutes scrolling for one. The whole point is under 60 seconds on-screen, then out the door with a piece of paper.
Demo
Code
How I Built It
The core is open-source AI running locally, so let me start there.
Gemma 3 4B via Ollama, with structured output. I didn't want to parse prose out of a model at runtime, so the model is constrained to a JSON schema and the result is validated with Pydantic:
response = client.chat(
model=OLLAMA_MODEL, # default: gemma3:4b
messages=[{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": prompt}],
format=OUTING_CARD_JSON_SCHEMA, # Ollama constrains generation
options={"temperature": 0.3},
)
data = json.loads(response.message.content)
card = OutingCard(**data) # Pydantic validates
Ollama keeps generation inside the schema; Pydantic catches the rest. If either fails, we retry once, and if Ollama is unreachable the app falls back to a template card, so it's never a dead end.
Weather without an API key. Open-Meteo's geocoding and forecast endpoints are free and keyless, so the only thing Trailhead ever sends over the network is a city name or a pair of coordinates. Everything else — the prompt, the model call, your notes — stays on the machine.
Rendering. render_html produces a self-contained file with print CSS, so "download" really means "print it and take it with you." fpdf2 produces a matching PDF. Both are pure Python.
Storage. A single SQLite file. Cards are serialized with model_dump_json() and read back through the same Pydantic models, so a saved card and a fresh one are the same object.
Stack: Python 3.15, Streamlit, httpx, the official ollama client, Pydantic, fpdf2, SQLite. No Node, no build step, no custom JavaScript.
Why Does Open Innovation Matter?
For Trailhead the answer is concrete:
-
It works where you actually need it. Generating a card is a local inference call — no cloud API. Once the model is pulled, the generator runs entirely against a local
ollama serve. A closed API would make the app useless the moment you lose signal, which is exactly where an outdoor app should work. - Location data never leaves the device. Trailhead knows where you walk. The only network call carries a city name or a coordinate to a keyless weather API — no account, no telemetry (Streamlit's usage stats are disabled in config), and no server holding a record of your habits.
-
The model is swappable.
OLLAMA_MODEL=llama3.2:3b streamlit run app.pyis the entire model-swap story. A 3B model is faster on a laptop; a larger one gives richer seasonal detail. You could fine-tune your own and point the same code at it — no provider, no pricing page, no rate limit. - It costs nothing to run. No keys, no billing, no quota. A hobby project that gets people outside shouldn't depend on anyone's credit card, least of all the runner's.
The open part isn't decoration. It's the reason the app can run offline, keep your data, and be changed by whoever runs it.
Prize Categories
I'm entering Best Use of Gemma — the entire card generator is Gemma 3 4B running locally through Ollama, constrained by a JSON schema and validated with Pydantic.
Top comments (0)