{"slug": "i-built-my-girlfriend-a-local-gemma-football-analyst-that-won-t-make-up-the", "title": "I built my girlfriend a local Gemma football analyst that won't make up the stats", "summary": "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.", "body_md": "*This is a submission for the [Hacktoberfest Weekend Challenge: Build for a Friend](https://dev.to/challenges/hacktoberfest-weekend-2026-10-01).*\n\n**MatchMind** is a local AI analyst for Brazilian football, built for **Bruna Boaventura, my girlfriend**.\n\nBruna 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.\n\nMatchMind 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:\n\nThe 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.\n\nA real answer generated locally by Gemma 3 4B (CPU only):\n\nLine-ups for a match, loaded on demand:\n\nSérie A history:\n\n*\"Interessante, pois traz dados históricos de 2003 até hoje, contendo gols e estatísticas.\"*\n\n(\"Interesting, because it brings historical data from 2003 until today, with goals and statistics.\")\n\nThat 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.)\n\n**Your local AI analyst for Brazilian football.** · *Seu analista de futebol brasileiro com IA local.*\n\nMatchMind 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.\n\n`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.\nQuick 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.\n\n```\nOpenFootball (results, CC0)  ──┐\nSérie A history CSVs (GPL-2.0) ┼─► Go API ─► deterministic stats, table, form\nOptional stats API + cache  ───┘      │\n                                      ▼\n                     compact JSON context for this question\n                                      ▼\n                        Gemma 3 4B via Ollama (local)\n                                      ▼\n            Go validates the JSON and adds FATO / INTERPRETAÇÃO\n```\n\n**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.\n\n**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.\n\n**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.\n\n**What real testing taught me.** Mocked tests passed, but running the real model exposed two problems:\n\n`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.\nI 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.", "url": "https://wpnews.pro/news/i-built-my-girlfriend-a-local-gemma-football-analyst-that-won-t-make-up-the", "canonical_source": "https://dev.to/darrkkens/i-built-my-girlfriend-a-local-gemma-football-analyst-that-wont-make-up-the-stats-4mb7", "published_at": "2026-10-03 02:02:04+00:00", "updated_at": "2026-10-03 02:08:02.387387+00:00", "lang": "en", "topics": ["ai-tools", "large-language-models", "ai-products", "developer-tools"], "entities": ["MatchMind", "Bruna Boaventura", "Gemma 3 4B", "Ollama", "OpenFootball", "Adão Duque", "Vue 3", "Go"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/i-built-my-girlfriend-a-local-gemma-football-analyst-that-won-t-make-up-the", "markdown": "https://wpnews.pro/news/i-built-my-girlfriend-a-local-gemma-football-analyst-that-won-t-make-up-the.md", "text": "https://wpnews.pro/news/i-built-my-girlfriend-a-local-gemma-football-analyst-that-won-t-make-up-the.txt", "jsonld": "https://wpnews.pro/news/i-built-my-girlfriend-a-local-gemma-football-analyst-that-won-t-make-up-the.jsonld"}}