This is a submission for the Hacktoberfest Week 1 "Touch Grass" challenge.
What I Built
PocketTrail is a small web app for people who want to look up from their phone for twenty minutes.
You tell it how much time you have (10, 20 or 30 minutes), where you are going (a park, a garden, your neighborhood, or just a window or balcony), what it is like outside (daytime, evening, rainy) and your mood (calm, curious, creative). You can add a note like "stay seated, no photos". It gives you three short things to notice, with durations that add up to the time you picked.
Then you save the walk to your device, put the phone away, and open it again when you want the next prompt. Saved walks work without a connection. There are no accounts, streaks, maps or feeds.
Demo
Live app: https://pockettrail-6dyu.onrender.com
The hosted demo runs in sample mode. It serves original, hand-written activities and makes no model call, and the page says so. I did not put a paid model or voice key on the public instance. The real model path works locally, which is what the numbers below come from.
Code
trakshan-mishra
/
pockettrail
A little less screen. A little more outside. Short nature activities with offline saved walks.
PocketTrail
A little less screen. A little more outside.
PocketTrail turns your time, setting, mood and outdoor conditions into three gentle nature activities. Save a walk on your device, then take a pause outdoors or by a window. Saved activity text works without a connection. Optional narration is available when ElevenLabs is configured.
Live demo: https://pockettrail-6dyu.onrender.com (free instance, so the first load after idle can take about a minute). The hosted demo runs in sample mode: it serves authored activities with no model calls and no voice. Model generation and narration need the configuration described below.
Created during the Hacktoberfest Week 1 2026 Touch Grass challenge. This repository covers Week 1 only.
Run locally
Requires Node.js 24 and Python 3.13+.
cp .env.example .env
bash scripts/dev.sh
Open http://127.0.0.1:8000. The script builds the production frontend so offline caching can be tested locally. For interface development run the backend separately and use…
Run it locally with bash scripts/dev.sh. The README covers Ollama, Backboard and ElevenLabs settings.
How I Built It
Stack. React and TypeScript on the front, FastAPI with Pydantic on the back, SQLite for cache and usage quotas, IndexedDB on the device for saved walks. One Docker image builds the frontend and serves it from FastAPI.
What the model does, and what it does not. My first instinct was to let the model write the activities. I dropped that quickly. A small model gets confident about things it cannot know, and this app tells people to go stand somewhere.
So the instructions are written by me, in a catalog of about fifteen activities per context. The model does two jobs:
- Pick three distinct activities that fit the request.
- Write a short personal "focus" line for each.
The server then checks the output against the catalog (setting, equipment, evening and rain rules), rejects duplicates and unknown activities, and assigns durations that sum exactly to the requested time. A rainy request can never return a daylight-only activity. A window request only draws from the window catalog. One validation repair is allowed; after that the request fails instead of looping.
Two small models, same cases. I ran qwen2.5-coder:3b and Phi-3-mini-128k through Ollama on my laptop, three identical requests each.
| Model | Valid packs | Mean latency |
|---|---|---|
| qwen2.5-coder:3b | 3 / 3 | 29.8 s |
| Phi-3-mini-128k | 3 / 3 | 67.4 s |
This is a small pilot, not a benchmark. Both passed the structural checks, so the more useful result was in what the checks missed when I read the outputs. Qwen suggested a stroll in its introduction even though the preferences said stationary. Phi claimed a heartbeat could be synchronized with breathing. I changed the introduction to authored text and added a rejection rule for heartbeat claims. Free-text wording can still get past a keyword check, so a human should read any pack before it goes in a demo. I also found the focus lines from the small model are sometimes generic or repeated. I did not fix that.
Qwen is a coding model. I used it because it was already installed, not because it is the best choice for this task.
Other checks. A script went through all 108 combinations of context, setting, mood and duration against the catalog and schema. A Docker image built and served the health endpoint as a non-root user, and I fixed a volume-permission failure that showed up there.
Keeping spend small. Identical requests reuse a cached response. Every hosted model attempt, including the repair, reserves a quota slot in SQLite before the call is made. Narration only runs when you press "Add voice", and it takes a saved pack ID, not arbitrary text. These are call and character limits, not dollar caps, and the README says so.
Offline. The shell, fonts, saved packs and any downloaded audio are stored locally. Offline phone use covers saved walks. Generating a new pack still needs a connection.
Timers. Walk Mode has an optional timer with a short chime made locally with Web Audio, plus vibration where the browser supports it. I tested this on desktop only. Phones can suspend audio and timers when the screen is locked, so I do not claim pocket reliability.
What I did not finish
- A real outdoor trial. I tested the flow in a desktop browser, not on a walk, so I have no field results to report.
- A physical phone test of offline reload, vibration and lock-screen behavior.
- Hosted model and voice. The code supports Backboard and ElevenLabs, but I made no real calls with either, so I am not listing them as integrations.
Why Does Open Innovation Matter?
The model here is replaceable. It is called through a thin adapter, so the same app ran against two different local models and can point at a hosted one by changing a few environment variables. That made the comparison above possible, and it meant I could read the model card, run it on my own machine, and keep preferences on the device when I chose local inference.
It also made the failures visible. With an open-weight model I could compare two models on the same inputs and see exactly where each one made things up. That is why most of the safety work ended up in the catalog and the validator, and not in a prompt asking the model to behave.
If you choose a hosted model, your preferences go to that provider. With local Ollama they stay on your machine.
Top comments (0)