# Touch Grass Card: a 270M Gemma in your browser that deals you a reason to go outside

> Source: <https://dev.to/qife422/touch-grass-card-a-270m-gemma-in-your-browser-that-deals-you-a-reason-to-go-outside-4mmh>
> Published: 2026-10-11 23:52:12+00:00

Everyone tells you to touch grass. Nobody tells you where to walk, what to look for, or how to make 30 free minutes feel like a tiny adventure instead of a lap around the block. So I built the smallest possible tour guide: an open-weight AI that lives entirely in a browser tab and deals you one outdoor mission at a time.

**Touch Grass Card** is a single web page. You tell it where you are (default: my college town, Corvallis, Oregon), how many minutes you can spare, and a vibe — chill, adventurous, curious, social. It then generates a mission card:

Repo: [github.com/qife422/touch-grass-card](https://github.com/qife422/touch-grass-card) — it's one HTML file plus this README. That's the whole app.

Live demo: [qife422.github.io/touch-grass-card](https://qife422.github.io/touch-grass-card/) (first load downloads the model once; after that it runs offline — try it in airplane mode).

The "brain" is **Gemma 3 270M** (instruction-tuned, ONNX export: `onnx-community/gemma-3-270m-it-ONNX`), running on-device via **Transformers.js 4.2.0**:

`fp32` weights (~1 GB one-time download) on both WebGPU and the WASM fallback. I originally tried the much smaller `q4f16` WebGPU weights, but ONNX Runtime has a known overflow bug for this model on the WebGPU fp16 path that makes it emit repeated unused tokens instead of English — no error, just garbage. fp32 is slower to download, but it is the path that actually works on both backends, so that is what the page ships.
There is no backend, no API key, no analytics. The only "prompt engineering" is a system message that forces a strict four-field output format, because a 270M model needs guardrails the way a golden retriever needs a fence.

Honest field notes on the model: 16 draws, zero garbled tokens — the fp32 fix held on real hardware (Chrome on Apple Silicon), so the `<unused>` bug I guarded against never showed up. The *semantic* reliability is the real story, though. Of the 16 missions, only about 3 were actually practical. Two ignored the safety instruction in the system prompt entirely: one proposed building a "Mobile Sensor Jammer" to "launch under the hood," and another ("Rain Cloud Rescue") told me to go find a kidnapped/missing person and call the police. Others were poetic but absurd — "The Whispering Willow" wants a handcrafted wooden box of fallen branches, and one card hallucinated the town completely ("Sunnyvale Weather Report," a city in California, emitting a forecast instead of a mission). The good ones felt genuinely personal — my final pick, "Unplug to Breathe," asked for a short, easy walk to a nearby park and a moment in the sun. A 270M model is a golden retriever: loyal, local, occasionally convinced the mailman is a mission.

Sunday morning, October 11, I took the "Unplug to Breathe" card literally: find a sunny spot, take a short, easy walk to a nearby park. (It was card 9 of 16 — the river card I wanted first turned out to be a 44-minute bus ride away, and I don't have a car, so the little model and I compromised.) After days of gray rain, Corvallis finally gave me blue sky — 46°F at 10 AM, jacket weather, but the sun made it feel generous. I found everything on the card's "look for" list: the grassy open space, the trees starting to turn, the sun. The card's "proof" field, true to form for this 270M model, wasn't actually a photo instruction — it just declared that walking to a park is the most effective way to get outside — so I photographed the park instead: blue sky, green lawn, an empty picnic table under a yellowing tree. Standing there with nothing urgent pulling at me, I felt the past week's rain and small frustrations dissolve a little. It beat scrolling, and it wasn't close.

---*Built over a weekend in Corvallis between classes. The code is MIT — fork it, swap the model, go touch grass in your own town.*
