fieldcards: a local Gemma turns your photos into a printed scavenger hunt

This is a submission for the Hacktoberfest Open-Source AI Challenge: Week 1 (theme: Touch Grass).
What I Built
fieldcards is a command-line tool that turns the photos on your laptop into a printed scavenger hunt.
You point it at a folder of photos from a park, a garden or a trail. Gemma 3, running locally through Ollama, looks at each one, works out the most findable thing in it, and writes a clue that doesn't name it. Each clue is drawn as a printed ASCII card. You print the sheet, leave your phone at home, and go find the real things.
The screen is the shortest part: about two minutes to make the sheet, then the rest of the afternoon outside.
+-[ #05 other ]----------------+ | | | Find a dark, weathered | | giant resting beside a | | rushing, silver stream. | | | +------------------------------+ - Green moss covering its surface - Dark, grey wood - A smooth, water-worn edge Where: Typically found in damp, shaded forest streams. [ ] found it time: ______ That card is real gemma3:4b output for a photo of a mossy log lying across a forest waterfall.
Demo
It's one command:
ollama pull gemma3:4b npm install -g github:KunalSiyag/fieldcards fieldcards ./photos --title "Saturday in the park" Here's a real run in my terminal. --stdout prints the cards right there, and progress goes to stderr, so fieldcards ./photos --stdout | lp sends them straight to a printer:
Every run writes three files:
-
index.html: a print-ready sheet, six cards per page, with the answer key on its own page. -
cards.txt: the same cards as plain text.--cols 32fits a 58 mm receipt printer. -
deck.json: everything Gemma said. Fix any mistakes, then reprint with--fromwithout running the model again.
--mode guide turns the same photos into a pocket field guide, with names and descriptions instead of riddles.
A real photo of mine
The run above used the only photo of my own I had on hand while writing this: the bar counter of a brewery I visited recently, taken from the floor above. It isn't an outdoor scene, but it shows the whole pipeline on a real, busy photo.
Gemma took 7 seconds and called it "round, reflective surfaces", with the clue "Find something that mirrors the light and reflects the surroundings around you." That's fair for such a busy scene, but it isn't what I'd want on a card. It's exactly the case deck.json is for: change the subject to "Oval bar counter", run fieldcards --from fieldcards-out/deck.json, and the sheet reprints without calling the model again.
Code
KunalSiyag / fieldcards
Turn outdoor photos into printable scavenger-hunt cards with a local Gemma model. Offline, private, screen-light.
fieldcards
Turn your outdoor photos into a printable scavenger hunt, with an open-weight model running on your own computer.
Each photo goes to Gemma 3, running locally through Ollama. Gemma works out what the photo shows and writes a clue for finding it that doesn't name it. altsvg then replaces every photo with a printed ASCII card holding that clue, the way altsvg turns alt text into a placeholder. You print the sheet, leave your phone at home, and go find the real things.
+-[ #05 other ]----------------+ | | | Find a dark, weathered | | giant resting beside a | | rushing, silver stream. | | | +------------------------------+ - Green moss covering its surface - Dark, grey wood - A smooth, water-worn edge Where: Typically found in damp, shaded forest streams. [ ] found it time: ______ That card came from a real gemma3:4b run on…
How I Built It
- Describe. Each photo goes to
POST /api/chaton the local Ollama server, together with a JSON schema informat. Gemma has to answer withsubject,category,description,clue,look_for,whereandconfidence, so a chatty reply can't break the layout. - Check. The answer is validated and trimmed. If a clue contains its own answer, the answer is blanked out, and low-confidence answers print as "best guess" on the card.
- Draw. The cards come from altsvg, an open-source library I wrote earlier that turns alt text into a same-size placeholder. Its ASCII style draws the
+--[ #01 other ]--+frame, both as SVG for the printed page and as plain text for the terminal andcards.txt.
Photos that were already described are matched by content hash and skipped on reruns, so you can add photos to the folder and run it again.
Tuning a 4B model
The prompt took three tries, and two of them taught me something:
- Example names leak. I added "Dandelion seed head" to the prompt as an example of a good name. On the next run Gemma labelled a waterfall photo "Dandelion seed head". Small models copy examples, so the final prompt has none.
- Strict wording makes it timid. When I told it to use "high" confidence only when certain, everything came back "low", and the names got vague ("Dark feathered observer"). The original, plainer prompt worked best. I kept it and added one rule so the clues don't all start with "Seek".
What it gets right and wrong
On my test photos Gemma reliably recognised common things: a dandelion clock, a maple leaf, a waterfall. Its clues don't give the answer away. It was weaker on specifics: a crow came back as "a sleek, dark bird", a soft pine pollen cone was described as "woody", and the brewery became "round, reflective surfaces". Its self-rated confidence is only a rough signal; it rated all three of those "high". That's why every answer lands in deck.json for you to check before printing, and why every sheet says "look, don't pick".
Why Open Matters Here
- No signal needed. The model runs on the laptop, so you can make cards at a cabin, a campsite or anywhere offline.
- Your photos stay yours. Photos carry faces, houses in the background and GPS in their metadata. Nothing is uploaded; the only request goes to
localhost. - It costs nothing to run. There's no API key and no per-photo bill, so a teacher can make a sheet for every class.
- It's swappable.
--modeltakes any vision model Ollama can run, and the JSON schema keeps the output the same shape.
On my laptop (RTX 3050, 4 GB), the first photo takes about two minutes because it also loads the model. Each photo after that takes 7 to 13 seconds, using about 2.9 GB of GPU memory.
What's Next
I haven't taken a printed hunt outside yet. That's the next step, and it's the test the whole design depends on. When I do, I want to find out:
- whether six cards is the right size for a 30 to 60 minute walk;
- whether the clues are fun to solve or too vague, especially the cards marked "best guess";
- how kids handle riddles like "a dark, weathered giant resting beside a rushing, silver stream".
I'll add an update to this post with photos of the sheet in use.
Prize Categories
Best Use of Gemma. Gemma 3 4B is the core of the project. It reads every photo locally and writes the card content through a JSON schema.
Credits
- Gemma 3 by Google, run locally with Ollama.
- altsvg is my own earlier open-source project (started in March 2026, published on npm). Its ASCII style was added this week for fieldcards.
- jpeg-js and pngjs decode photos for the optional
--artmode, which also prints the photo itself in characters. - Test photos from Wikimedia Commons: the crow by Alexis Lours (CC BY 4.0) and the waterfall by Dietmar Rabich (CC BY-SA 4.0). The brewery photo is mine.
- Built with help from Claude Code.

