This is a submission for the Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass
What I Built
OpenQuest is an AI-powered adventure generator that encourages users to step outside, explore their surroundings, and complete real-world quests. Instead of giving endless recommendations or summaries, it creates actionable challenges that push people to interact with places, people, and experiences around them.
The idea is that once you accept, your phone's internet is cut for an hour. No doomscrolling. Navigation and emergency calls still work. You walk there, take the photo, and an AI model checks it. Pass, and the phone unlocks. Run out the clock, and it unlocks anyway. There's a 24-hour panic PIN for emergencies, because a lock you can't escape is a hostage situation, not a habit.
It's for anyone who has said "I'll just check my phone for a minute" and looked up an hour later. It's also for people who don't trust an app to lock their phone unless they can read how it works.
Here's the loop:
- Get a quest. A small model running in your browser looks at real places near you (from OpenStreetMap), the time of day and the weather, and writes a quest.
- Phone locks. A tiny Android companion app cuts other apps' internet for the hour.
- Take the photo. The photo's GPS has to land inside the quest radius first. Only then does the model look at what's in the picture.
- Unlock. Pass and you're free. If the hour ends, you're free anyway. ### Where it actually stands
Quest lifecycle
stateDiagram-v2
[*] --> pending: generated
pending --> active: user accepts, phone locks
pending --> abandoned: user gives up
active --> submitted: photo taken
submitted --> verified: judge passes, phone unlocks
submitted --> failed: judge or GPS rejects
failed --> submitted: retry while time remains
active --> expired: 60 min elapsed
failed --> expired: 60 min elapsed
active --> abandoned: panic PIN
verified --> [*]
expired --> [*]
abandoned --> [*]
Video Walkthrough
Code
🌿 OpenQuest
Open-source quests that lock you out until you touch grass.
An on-device AI writes a short outdoor quest, your phone locks until you've done it, and the same AI checks your photo. No cloud model, no tracking, no server you don't control.
Live demo · Video · How it works · Architecture · Get started · Roadmap
📸 Screenshots
Mobile-first and responsive from 320 px to desktop. Quests in these screenshots are sample data; on-device generation needs WebGPU.
🌐 Live demo
🚀 Try it: the web app is live at openquest-pi.vercel.app. The Android companion and Worker are not published yet.
Link Web app (PWA) openquest-pi.vercel.app Companion APK TODO: add the GitHub Releases link once a release is cut Worker (optional sync) TODO: add URL once deployed
🎬 Demo video
🚧 Coming soon. The shot list is in
docs/DEMO_SCRIPT.md.
✨ What
…Apache-2.0. It's a pnpm monorepo: the PWA in apps/pwa, the Android companion in apps/companion, an optional Cloudflare Worker in apps/worker.
How I Built It
The model. Gemma 4 E2B, run in the browser through Transformers.js on WebGPU, inside a Web Worker so the UI doesn't freeze. There are two builds: a 2-bit mobile one (about 2.6 GB) and a 4-bit one (about 3.4 GB). No API key, no server, no per-quest cost.
Writing a quest. The app asks OpenStreetMap's Overpass API for places within about 2 km, adds time, season and weather, and gives the model a short list of real candidates. The model has to answer in JSON that matches a schema. If it doesn't, or if the quest fails the safety check, the app falls back to a hand-written template instead of showing you something strange.
The safety filter. An LLM telling people to go outside needs a net under it. Every quest goes through a plain regex filter that rejects climbing, swimming, trespassing, foraging, approaching animals or strangers, and so on. It's deliberately dumb and deliberately readable, so anyone can open the file and argue with it.
Judging the photo. The model's verdict is advisory. The check runs in this order: is the photo's GPS inside the quest radius? If not, it fails no matter what the model says. A model can be talked into believing a stock photo is a bakery. A coordinate can't.
The lock. A web page can't lock a phone, so a small Kotlin app does it: a VpnService that drops traffic, and a localhost server (127.0.0.1:7777) that the web app talks to. Every request is HMAC-signed and rejected if it's more than 30 seconds old, so nothing on the network, and no other app, can trigger a lockout.
For phones that can't run the model. An optional Cloudflare Worker acts as a mailbox: the phone sends the photo, a laptop that can run Gemma judges it and sends the verdict back.
🏗️ Architecture
OpenQuest is two required parts and one optional part.
flowchart LR
subgraph Phone["📱 Phone"]
subgraph PWA["PWA (React + Vite)"]
UI[UI<br/>React Router]
QS[Quest service<br/>+ safety filter]
DB[(IndexedDB<br/>quests, photos)]
subgraph W["Web Worker"]
G[Gemma 4 E2B<br/>Transformers.js]
end
end
subgraph C["Android companion (Kotlin)"]
HS[Localhost server<br/>127.0.0.1:7777]
VPN[VpnService<br/>lockout]
KS[(Keystore<br/>panic PIN)]
end
end
OSM[(OpenStreetMap<br/>Overpass)]
WX[(Open-Meteo<br/>weather)]
subgraph CF["☁️ Cloudflare (optional)"]
WK[Worker<br/>Hono + GitHub OAuth]
D1[(D1)]
R2[(R2 photos)]
end
Laptop[💻 Laptop PWA<br/>runs Gemma, judges]
UI --> QS
QS --> DB
QS <--> G
QS -- POIs --> OSM
QS -- weather --> WX
QS -- "HMAC-signed JSON" --> HS
HS --> VPN
HS --- KS
UI -. field mode .-> WK
WK --- D1
WK --- R2
Laptop -. polls mailbox .-> WK
Why Does Open Innovation Matter?
If OpenQuest were built on a closed API, every one of those would flow through someone else's server. Your coordinates, your photos, a bill per quest, and a verdict from a model you can't inspect, which stops working the day the API changes or the money runs out.
Open weights changed what was possible:
- The judge runs on your device. Your photo never leaves your phone. A closed API can promise that. An on-device model lets you check it.
- The lock is about 900 lines of Kotlin. You can read the thing that controls your phone's network in an afternoon.
- The safety rules are a file, not a policy. If the filter is too strict or too loose, you send a pull request, instead of an email to a support address.
- It costs nothing to run per quest, so there's no reason to ever add ads or a subscription to pay for inference. I'll be fair about the price. On-device means a 2.6–3.4 GB first download, and it needs a browser with WebGPU. That's a real cost. For this app, I'd rather pay it in gigabytes than in trust.
## Final Thoughts
The internet is full of products competing for attention.
OpenQuest explores a different question:
What if AI's best contribution isn't keeping us online longer, but giving us a reason to close the laptop and go somewhere?
Sometimes the next adventure is only a few steps away.
OpenQuest simply gives you a nudge to find it.





Top comments (0)
Some comments may only be visible to logged-in visitors. Sign in to view all comments.