I built my girlfriend a local Gemma football analyst that won't make up the stats A developer built MatchMind, a local AI football analyst for Brazilian Série A, for his girlfriend Bruna Boaventura, who struggled to find Brazilian club results and historical data in one place. The system pairs a Vue 3 Portuguese-language dashboard and a Go REST API with Gemma 3 4B running locally via Ollama, enforcing that all numbers come from data or deterministic code rather than the model, which answers "Indisponível" when data is missing. The developer reports that computed season tables match the official champions list for all 22 seasons and that a name-matching routine links 95% of starting line-ups. This is a submission for the Hacktoberfest Weekend Challenge: Build for a Friend https://dev.to/challenges/hacktoberfest-weekend-2026-10-01 . MatchMind is a local AI analyst for Brazilian football, built for Bruna Boaventura, my girlfriend . Bruna had a hard time finding Brazilian clubs' results and historical data. So I built her one place to look things up — and a way to just ask. MatchMind puts the numbers together and lets her ask questions in Portuguese to an AI that runs on her own computer . You pick a club and get: The rule behind everything: the numbers come from data or from deterministic code, never from the model. If something is missing, MatchMind says "Indisponível" instead of guessing. A real answer generated locally by Gemma 3 4B CPU only : Line-ups for a match, loaded on demand: Série A history: "Interessante, pois traz dados históricos de 2003 até hoje, contendo gols e estatísticas." "Interesting, because it brings historical data from 2003 until today, with goals and statistics." That was exactly the gap she had: the history is what made it useful for her. To be precise about coverage: the historical dataset runs from 2003 to 2024, and the current 2026 season comes from a separate live source. Your local AI analyst for Brazilian football. · Seu analista de futebol brasileiro com IA local. MatchMind is a Brasileirão dashboard with a Vue 3 interface in Brazilian Portuguese , a Go REST API and an open-weight model Gemma running locally through Ollama . Pick a club and see the league table, recent form, the last matches with statistics, scorers, cards and lineups, 20+ seasons of Série A history, and ask an AI analyst questions that are answered only from that data. FATO from INTERPRETAÇÃO and must say when data is missing. pgx for an optional PostgreSQL cache . /api/chat with structured JSON output. go vet , go test -race and the frontend build, plus contributing guide and issue templates. Quick start: ollama pull gemma3:4b , then go run ./cmd/server in backend/ and npm run dev in frontend/ . No account and no API key are needed. OpenFootball results, CC0 ──┐ Série A history CSVs GPL-2.0 ┼─► Go API ─► deterministic stats, table, form Optional stats API + cache ───┘ │ ▼ compact JSON context for this question ▼ Gemma 3 4B via Ollama local ▼ Go validates the JSON and adds FATO / INTERPRETAÇÃO Data I can trust. Results come from OpenFootball https://github.com/openfootball/football.json CC0 . The 2003–2024 history comes from Adão Duque's Brasileirão dataset https://github.com/adaoduque/Brasileirao Dataset , downloaded at runtime. I computed every season's final table from the results, and the champions match the official list for all 22 seasons; the scorers file matches the final score in 100% of matches since 2015. Where the source has gaps its 2016 and 2024 statistics are mostly zeros , MatchMind drops those averages instead of showing fake numbers. Linking sources without guessing. Per-match statistics, scorers and line-ups come from an optional API. A match only receives that data when round, opponent, home/away side and final score all agree with OpenFootball. Line-ups abbreviate names "G. Gómez" while player stats use full names "Gustavo Gómez" , so I wrote a matcher that understands initials. It links 95% of starters; the rest nickname vs. legal name are shown without numbers rather than guessed. Every API response is cached — in PostgreSQL if you run docker compose up — so a finished match costs one request, ever. Grounding the model. The browser never sends context. For each question, Go rebuilds the club snapshot and sends Gemma a JSON envelope that keeps the data separate from the question and is explicitly treated as untrusted. Gemma returns facts , interpretation and sources used ; Go validates the structure and the allowed source names and adds the labels itself. What real testing taught me. Mocked tests passed, but running the real model exposed two problems: serie a titles 2003 2024 only . The next answer said "4 Série A titles between 2003 and 2024" — the answer you see in the screenshot above. When a rule really matters like flagging sample data from an API test key , Go appends the warning itself instead of trusting the model. ollama pull gemma3:4b , there's no per-question fee, no AI account and no key to protect. The football data sources used by default are open too. gemma3:12b on a stronger machine with one environment variable. I built MatchMind with the help of an AI coding assistant Claude Code , which I directed, reviewed and tested throughout. All data, screenshots and the model answer shown above come from running the real application.