This is a submission for the Hacktoberfest Open-Source AI Challenge: Week 1 — Touch Grass.
✏️ TODO before publishing: fill every
TODObelow, then delete this line.
What I Built
Side Quest turns the streets around you into a short scavenger hunt.
You tell it how long you have (15 to 60 minutes) and what kind of clues you like (playful, poetic, detective, or for kids). It finds a few interesting places within walking distance (a temple, a mural, an old bookshop, a pond) and plans a loop that fits your time. Then Gemma, running inside your browser, writes a riddle for each stop.
Then you put the phone away.
When you think you've found the place, you check in. The app shows you one small thing to notice before you move on: count the bells, find the oldest crack in the wall, listen for one sound that repeats. At the end, Gemma writes a three-line postcard about the walk. It is saved only on your device.
Most "AI + outdoors" apps keep you looking at the screen while you're outside. I wanted the opposite: the screen is on for about ten seconds per stop, and the rest of the time you're looking at the street.
TODO (your own words, 2–3 sentences): why you wanted this. Who would you hand it to? A friend who never leaves the hostel? Yourself after a 10-hour study day?
Demo
- Live app: https://hacktoberfest-26.vercel.app
- Try it from your desk: https://hacktoberfest-26.vercel.app/?at=18.5195,73.8553&sim starts you at Shaniwar Wada in Pune and adds a Teleport button, so you can play a whole quest without walking.
You need a browser with WebGPU for the model: Chrome on Android 12+, or Chrome/Edge on Windows or macOS. The first run downloads Gemma once (~0.7 GB). Without WebGPU, the walk still works with simple built-in clues.
TODO: a 30–60s screen recording, or 3 screenshots: clue → "Found it" → postcard
Code
Side Quest
A short walking scavenger hunt around wherever you're standing. The clues are written by Gemma, running entirely in your browser (WebGPU via WebLLM) Your location never leaves the phone.
Built for the Hacktoberfest Open-Source AI Challenge, Week 1: Touch Grass.
How it works
- Pick how long you have (15–60 min) and a clue style (playful, poetic, detective, for kids).
- The app finds interesting places nearby from OpenStreetMap and Wikipedia: parks, temples, murals, old trees, bookshops, historic buildings.
- A small planner picks a loop of 2–4 varied stops that fits your time.
- Gemma writes a riddle for each stop plus one small thing to notice when you get there.
- Put the phone away. Check in when you think you've found it (it buzzes if the screen is on).
- At the end, Gemma writes you a three-line postcard of the walk, saved only on your device.
Why
…MIT licensed. About 1,000 lines of TypeScript, no framework.
How It Works
your phone ──► snap location to a ~1 km grid square
──► OpenStreetMap + Wikipedia: "what's interesting in this square?"
──► planner: pick 2–4 varied stops that fit your time
──► Gemma (WebGPU, in a Web Worker): write a riddle per stop
──► walk · check in · notice something · next clue
──► Gemma: write a postcard of the walk → saved on the device
1. Finding places, with two free and keyless sources. OpenStreetMap (via the public Overpass API) gives the small stuff: parks, temples, murals, named bakeries, old trees. Wikipedia's geosearch API gives named landmarks with a line of description, which turns out to be great riddle material. Near Shaniwar Wada in Pune, one query returned 188 candidate places.
2. Planning the loop, deliberately without AI. A small randomised search tries 400 greedy loops and keeps the one with the most stops, the most variety (it heavily penalises a second temple in a row), and a total time closest to what you asked for. Walking speed is 70 m/min and streets get a 1.3× detour factor. A planner is the right tool here: it's deterministic and checkable, and a 1B model is bad at geometry.
3. Writing the clues, which is where the model earns its place. Each stop's OpenStreetMap tags and Wikipedia summary go to Gemma with one job: hint at the place without naming it, and suggest one thing to notice with your senses.
const prompt = `You write clues for a real-world walking scavenger hunt.
The walker must find this place: ${describe(place)}.
Write:
1. A riddle of at most two short sentences that hints at the place without saying its name.
Use what someone would see, hear or smell there.
2. One small thing to notice once they arrive, using their senses. One sentence.
Tone: ${VOICE[vibe]}. No emoji. No hashtags.
Reply in exactly this format and nothing else:
CLUE: <riddle>
NOTICE: <thing to notice>`;
If the model's answer can't be parsed, or it gives the name away, a template clue takes over and the screen says so honestly.
TODO: paste 2–3 real clues Gemma wrote for you, with the place each one was for. Real output is more convincing than any description.
Why Open Matters Here
This is the part I care about most.
A hosted model would need your live location for every clue. Here nothing about where you're standing ever reaches an AI provider, because the AI provider is your own GPU. Gemma runs in the browser through WebLLM on WebGPU, inside a Web Worker.
The only network requests are the map lookups, and even those never carry your exact position. The query box is snapped outward to a 0.01° grid (about 1.1 km) before it leaves the phone:
/**
* A bounding box snapped outward to a 0.01° grid (~1.1 km). This is the only
* thing about your location that ever leaves the phone: the map server learns
* which grid squares you asked about, never the point you're standing on.
*/
export function snappedBbox(c: LatLng, radiusM: number) { … }
Everyone standing anywhere in the same square sends the identical request.
The rest follows from using open pieces:
- It costs nothing to run. There are no API keys and no accounts. It's a static site plus one tiny cached relay function on Vercel's free tier. With a closed model API I'd be paying per riddle, or asking you for a key.
- It works offline after the first run. The model weights are cached by the browser, and map results are cached per area for a week, so a second walk in the same neighbourhood works with no signal at all.
-
The model is swappable. You can pick Gemma 3 1B (~0.7 GB, sized for phones) or Gemma 2 2B (~1.4 GB, better clues on a laptop). Swapping is one line in
MODELS.
What Went Wrong (and What I Changed)
-
The public Overpass server turns away browsers. It worked from my dev machine, then failed on the deployed site:
overpass-api.deanswers anonymous browser requests with406 Not Acceptableand no CORS header, so the browser reports a CORS error that hides the real reason. The server wants clients to identify themselves, and a browser isn't allowed to setUser-Agent. The fix is a ~50-line Vercel function,api/places.ts. It accepts only a grid-snapped box (anything off-grid or over ~9 km is rejected), sends the fixed query with an identifyingUser-Agent, falls back across four mirrors, and setss-maxage=604800so the CDN answers repeat boxes for a week without touching OpenStreetMap at all. -
Even when it identified itself, Overpass was often overloaded, with
504 Gateway Timeoutmore often than not during testing. So OpenStreetMap and Wikipedia run in parallel, OSM gets a hard time budget, and either source alone is enough to plan a walk. -
Wikipedia was silently dropping most results. The geosearch generator returned 47 pages, but only 10 had coordinates attached.
prop=coordinateshas its own limit (colimit) that defaults to 10. Addingcolimit=maxtook the area from 1 usable landmark to dozens. -
'gpu' in navigatoris not enough. A browser can expose WebGPU and still have no usable adapter. Chrome on Linux does exactly that by default. The check now actually callsrequestAdapter(), and if the model can't start, the walk still happens with built-in clues instead of an error screen. - Browsers pause GPS when the screen is off. I can only buzz you on arrival while the screen is on. Otherwise you tap I think I'm here. Honestly, that turned out to be part of the fun.
I Took It Outside
TODO (bonus points, and the best part of the post): go on 1–3 real walks. Where did it send you? Which clue made you laugh, and which was too vague? What did you find that you'd walked past for years? Add a photo or two.
What's Next
- Fine-tune a small Gemma on good riddles, since the 1B model's clues vary in quality.
- A "share this quest" link, so friends can walk the same route without either of you sending your location anywhere.
- Hindi and Marathi clues.
Prize Categories
Best Use of Gemma. Gemma is the only AI in the app. It runs entirely on-device via WebGPU and writes every clue and postcard.
Map data © OpenStreetMap contributors (ODbL). Wikipedia text CC BY-SA. Built with AI assistance (Claude Code) for the scaffolding and debugging.
Top comments (0)