This is a submission for the Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass
What I Built
GPlay answers one question fast: "We've got five people, a ball, and a patch of grass — what can we actually play, right now?"
You tell it how many people you have, what's in your bag, and where you are. It filters a library of real-world games down to the handful that genuinely fit those constraints, then uses Gemma (open weights, running locally through Ollama) to write a short, tailored playbook — setup, how to play, how to win — adapted to your group size, equipment, and space.
The goal is to make the screen the shortest part of the experience. Open GPlay, get a pick, read three bullets, walk outside.
It has three views:
- Home / Coach — describe your group ("4 kids and 2 adults, one frisbee, small yard") and it suggests playable game cards you can tap for rules. Ask it something unrelated and it politely refuses and steers back to games.
- Games Catalog — the full local library with search and area filters. Every card opens streamed, adapted rules.
- Scoreboard — pick any game and log scores, with a ranked table per game.
Demo
Run it yourself in two commands:
# local Ollama: ollama serve && ollama pull gemma4:latest
docker compose up --build
then open http://localhost:5173.
Code
GPlay
An open-source, local-first web app for the Hacktoberfest "Touch Grass" challenge Tell it how many people you have, what equipment is on hand, and where you are — it instantly filters matching physical games and uses Google's open-weight Gemma model (via Ollama) to stream tailored rules, setups, and adaptations as Markdown over SSE.
Zero cloud APIs, zero API fees, works fully offline.
Architecture
[ React + Tailwind ] --REST/SSE--> [ FastAPI ] --filter--> [ SQLite games DB ]
\
'--local HTTP--> [ Ollama: gemma4:latest ]
Quick start
Docker
# Uses Ollama installed on your machine (ollama serve + ollama pull gemma4:latest)
docker compose up --build
# No local Ollama? Run everything in containers instead:
docker compose --profile containerized-ollama up --build
Serves the frontend at http://localhost:5173. OLLAMA_URL/GPLAY_MODEL
env vars override the defaults (http://host.docker.internal:11434 / gemma4:latest).
Manual
1. Backend
cd server
uv venv && uv pip…How I Built It
Stack: React 19 + Vite + Tailwind CSS on the front end, FastAPI on the back end, SQLite for the seeded 29-game catalog, and Ollama serving gemma4:latest for every bit of language generation.
Architecture:
[ React + Tailwind ] --REST/SSE--> [ FastAPI ] --filter--> [ SQLite games DB ]
\
'--local HTTP--> [ Ollama: gemma4:latest ]
A few decisions worth calling out:
The model only does what it is good at. "Which of these 29 games fit 4 people with one frisbee on grass?" is a deterministic filter — so it is plain Python/SQL, not a prompt. Gemma is handed only the games that already match and asked to adapt them. That keeps results fast, predictable, and cheap, and it means a small local model behaves well.
Everything streams. Rules and chat are streamed token-by-token from FastAPI as Server-Sent Events and rendered as Markdown with react-markdown, so the playbook starts appearing immediately instead of after a long wait.
The chat markers never leak. The Coach prompt is restricted to physical games only. When it wants to show game cards it emits a GAMES_PICK: id,id,id line, which the backend strips out line-by-line mid-stream and converts into a structured {"games": [...]} event. The user sees prose plus cards; the plumbing stays invisible.
The model can invent new games — under constraints. A separate endpoint has Gemma return strict JSON for a brand-new game, then validates it before storing: equipment and areas must be from the allowed sets, player counts are clamped, and the slug is de-duplicated. Bad model output is rejected, not saved.
The AI is optional by design. If Ollama or the model isn't running, /api/rules and /api/chat fall back to deterministic, built-in rules, streamed with the same token-by-token behaviour. The app works end-to-end offline — the AI is an upgrade, not a dependency.
Why Does Open Innovation Matter?
This is an app you're supposed to use outside — in a yard, a park, a campsite, the backcountry. That makes the open approach the whole point:
- It runs with no internet. Inference happens on the machine in front of you. No signal required, no round-trip to a server that might be slow or down. A bird-call-style "works on the trail with no bars" promise, applied to play.
- No data leaves your machine. A group's location, ages, and habits stay local. There is no vendor seeing which games a school picked or where a run club meets.
- No API keys, no per-request cost. Open weights mean the app costs nothing to run. A teacher, a parent, or a run-club organiser can clone it and use it without a billing account.
-
The model is swappable.
GPLAY_MODELis an env var. Point it at a different Ollama model, a fine-tune, or a smaller model for a weak laptop — nothing else changes. A closed API would lock both the model and the terms.
Where open beat closed here: GPlay works on a phone in a backyard with no cell service, adapts everything to a group's real situation without sending that situation anywhere, and stays free forever to the people who'd benefit most from it.
Prize Categories
- Best Use of Gemma — the project's language generation is Gemma via local Ollama: adapted rules, the Coach chat, and constrained new-game generation all run through it.
Team
Solo — @justcallmemarko.
Top comments (0)