Two minutes on a screen, an hour outside: an offline photo scavenger hunt powered by Gemma 4 + Ollama. Hacktoberfest 2026 Touch Grass.
Python
0
2 commits
updated Oct 6, 2026
Two minutes on a screen, an hour outside. An offline photo scavenger hunt powered by Google's open-weight Gemma 4, running on your own computer with Ollama.
No account, no upload, no internet needed. Your photos (and their location data) never leave the computer.



ollama pull gemma4:e2b # ~4.6 GB; gemma4:e4b also works if you have the memory
pip install -r requirements.txt # Pillow, for EXIF + resizing
python3 server.py # open http://127.0.0.1:8777
Tested on a laptop with a 6 GB GTX 1660 Ti: a quest card takes ~30 s, checking a photo ~25-35 s.
Settings: QUEST_MODEL, QUEST_OLLAMA_URL, QUEST_HOST, QUEST_PORT.
Checking photos is slow on a laptop (~30 s each), so a 40-photo walk takes about 20 minutes. In the plain mode the browser loops over the photos, and closing the tab, the laptop sleeping, or Ollama running out of memory loses the rest. With a local Temporal server, each walk becomes a workflow and each photo an activity:
temporal server start-dev --db-filename ~/.outside-quest/temporal.db # open source, runs locally
python3 server.py # detects it: "durable checking via Temporal"
~/.outside-quest/walks/ first, so you can close the tab right after uploading.Tested by stopping Ollama and then killing the app server in the middle of a 6-photo walk. The red bar is the photo that failed while Ollama was down; attempt 4 succeeded once it was back, and all 6 photos were checked:

Without Temporal running, the app works exactly as before.
Messaging apps such as WhatsApp strip EXIF data, and iPhone sharing can leave location out. The journal now says so ("no location in 2 of 5 photos") instead of silently showing no map. Copy originals over USB or AirDrop.
I first built a plant/bird identifier. Then I tested it. On six photos, gemma4:e2b called a Common Myna a
"Jackdaw" with high confidence, and gemma4:e4b called it a "Weaver Bird", also with high confidence.
Neither named the Monarch butterfly or the neem tree; asking for a top-3 list didn't fix it. A tool that tells
you the wrong bird with confidence is worse than no tool.
But both models were reliably right about the coarse question: is there a bird? a butterfly on a flower? a mushroom? a storm cloud? So the app asks the model only what small open models are good at, and leaves the naming to you and a field guide. On the six test photos, every main subject was matched to the right quest.
Quests written by the model pass through plain-code filters before you see them:
A completed quest must come with a non-empty description of the visible evidence, and quest IDs are constrained with a JSON schema, so the model can't invent quests or award points without saying why.
server.py: Python standard library plus Pillow. Two endpoints: /api/quests (structured-output quest card)
and /api/check (reads EXIF time + GPS, resizes to 1024 px, asks Gemma which quests the photo completes).durable.py: optional Temporal workflow (CheckWalk) and activity (check_one), with a worker that runs inside the server.static/index.html: one file, no framework. Quest card, a full-screen "phone away" timer, results board,
badges, journal and an SVG route drawn from the photos' coordinates (no map tiles, so it works offline).samples/ holds six Wikimedia Commons photos used for testing (credits in samples/CREDITS.md).
samples/demo-walk/ holds the same photos with made-up timestamps and GPS points, only to demo the journal.
MIT
Two minutes on a screen, an hour outside: an offline photo scavenger hunt powered by Gemma 4 + Ollama. Hacktoberfest 2026 Touch Grass.
Python
0
2 commits
updated Oct 6, 2026
Two minutes on a screen, an hour outside. An offline photo scavenger hunt powered by Google's open-weight Gemma 4, running on your own computer with Ollama.
No account, no upload, no internet needed. Your photos (and their location data) never leave the computer.



ollama pull gemma4:e2b # ~4.6 GB; gemma4:e4b also works if you have the memory
pip install -r requirements.txt # Pillow, for EXIF + resizing
python3 server.py # open http://127.0.0.1:8777
Tested on a laptop with a 6 GB GTX 1660 Ti: a quest card takes ~30 s, checking a photo ~25-35 s.
Settings: QUEST_MODEL, QUEST_OLLAMA_URL, QUEST_HOST, QUEST_PORT.
Checking photos is slow on a laptop (~30 s each), so a 40-photo walk takes about 20 minutes. In the plain mode the browser loops over the photos, and closing the tab, the laptop sleeping, or Ollama running out of memory loses the rest. With a local Temporal server, each walk becomes a workflow and each photo an activity:
temporal server start-dev --db-filename ~/.outside-quest/temporal.db # open source, runs locally
python3 server.py # detects it: "durable checking via Temporal"
~/.outside-quest/walks/ first, so you can close the tab right after uploading.Tested by stopping Ollama and then killing the app server in the middle of a 6-photo walk. The red bar is the photo that failed while Ollama was down; attempt 4 succeeded once it was back, and all 6 photos were checked:

Without Temporal running, the app works exactly as before.
Messaging apps such as WhatsApp strip EXIF data, and iPhone sharing can leave location out. The journal now says so ("no location in 2 of 5 photos") instead of silently showing no map. Copy originals over USB or AirDrop.
I first built a plant/bird identifier. Then I tested it. On six photos, gemma4:e2b called a Common Myna a
"Jackdaw" with high confidence, and gemma4:e4b called it a "Weaver Bird", also with high confidence.
Neither named the Monarch butterfly or the neem tree; asking for a top-3 list didn't fix it. A tool that tells
you the wrong bird with confidence is worse than no tool.
But both models were reliably right about the coarse question: is there a bird? a butterfly on a flower? a mushroom? a storm cloud? So the app asks the model only what small open models are good at, and leaves the naming to you and a field guide. On the six test photos, every main subject was matched to the right quest.
Quests written by the model pass through plain-code filters before you see them:
A completed quest must come with a non-empty description of the visible evidence, and quest IDs are constrained with a JSON schema, so the model can't invent quests or award points without saying why.
server.py: Python standard library plus Pillow. Two endpoints: /api/quests (structured-output quest card)
and /api/check (reads EXIF time + GPS, resizes to 1024 px, asks Gemma which quests the photo completes).durable.py: optional Temporal workflow (CheckWalk) and activity (check_one), with a worker that runs inside the server.static/index.html: one file, no framework. Quest card, a full-screen "phone away" timer, results board,
badges, journal and an SVG route drawn from the photos' coordinates (no map tiles, so it works offline).samples/ holds six Wikimedia Commons photos used for testing (credits in samples/CREDITS.md).
samples/demo-walk/ holds the same photos with made-up timestamps and GPS points, only to demo the journal.
MIT