{
  "$type": "site.standard.document",
  "bskyPostRef": {
    "cid": "bafyreicxzpdd5ds4ih5fgcihdzt3ck7e47j75y4jucs7jby7ma4skkqoxa",
    "uri": "at://did:plc:25rdn5elo5izoxrmtis34zuk/app.bsky.feed.post/3mpj5ukfos6j2"
  },
  "coverImage": {
    "$type": "blob",
    "ref": {
      "$link": "bafkreibixrya7zzqqnkg2ykbu473avof2ebek4p2d6ovhio7gkhdtiziea"
    },
    "mimeType": "image/webp",
    "size": 282622
  },
  "path": "/kristjan_vinderslev_95824/i-built-an-ai-that-predicts-football-matches-before-kickoff-and-forces-it-to-stay-honest-265l",
  "publishedAt": "2026-06-30T13:30:00.000Z",
  "site": "https://dev.to",
  "tags": [
    "ai",
    "webdev",
    "supabase",
    "showdev",
    "Odds Radar Pro",
    "track-record page",
    "oddsradarpro.com/en/resultater"
  ],
  "textContent": "Most football \"tipster\" sites have the same trick: they show you the winners and quietly bury the losers. I wanted to build the opposite — an AI that commits to a prediction _before_ a match starts, logs it, and then shows you whether it was right or wrong. No cherry-picking, no editing history after the fact.\n\nThat tool is now live as Odds Radar Pro. Here's how it works under the hood, and the design decisions that took the longest to get right.\n\n##  The core idea: don't trust the market, measure against it\n\nA bookmaker's odds are basically a probability with a profit margin baked in. The naive approach is to copy the market and shave the margin. I went the other way.\n\nThe AI builds its **own** probability for every match — home win, draw, away win, over/under 2.5 goals, both teams to score — from real signals: recent form, goals scored and conceded, head-to-head history, key players, injuries, lineups. Only _after_ it has its own number does it look at the market. The gap between the two is the whole product: that's where a game is mispriced, and that's where value lives.\n\nThe important rule: the AI never blends the market into its own estimate. If it did, it would just slowly converge on the bookmaker and find nothing. It self-calibrates against its own historical hit rates instead, anchored to football's base rates.\n\n##  The stack\n\nNothing exotic — I'm a solo, mostly non-technical builder, so \"boring and readable\" beats \"clever\":\n\n  * **Vite + React + TypeScript** on the front end\n  * **Supabase** for auth and storage\n  * **Vercel** for hosting and cron jobs\n  * **API-Football** as the single source of fixtures, odds, stats and injuries\n\n\n\nEverything heavy runs in Vercel cron. A few times a day a job pulls the day's fixtures with odds, runs each match through the model once (cached so it never re-bills the same match), and stores the result.\n\n##  The part I'm most proud of: keeping it honest\n\nTwo design decisions make the track record trustworthy:\n\n  1. **Picks are only logged before kickoff.** There is zero retro-analysis of matches that already happened. If the model didn't commit before the whistle, it doesn't count.\n  2. **Every confident, correct call becomes a public page.** When the AI's pre-match pick lands with high confidence, a cron job writes a server-rendered article: what the AI predicted, what the market gave, and the actual result. They're all collected on a public track-record page.\n\n\n\nThat second part doubles as organic SEO — real, server-rendered content that search engines and AI answer engines can read and cite. Each page ships with structured data (NewsArticle + SportsEvent), hreflang for Danish/English, and a dynamic sitemap.\n\n##  What I'd tell another solo builder\n\n  * **Cache aggressively when you pay per API call.** My biggest early bug was a function that silently failed on file-shaped responses and quietly re-billed. A connection indicator and retries everywhere fixed the trust problem.\n  * **Log before you predict, not after.** It's tempting to \"evaluate\" past results. Don't. The discipline of committing first is the entire value of a track record.\n  * **Ship in your own language first if it's your edge.** I kept the main app in Danish because it's a real niche advantage for a one-person project.\n\n\n\nIf you want to see it working, the live track record is here: **oddsradarpro.com/en/resultater**. It only shows matches where the AI made a confident call before kickoff — and got it right.\n\n_Gamble responsibly. This is an analysis tool, not a guarantee. 18+._",
  "title": "I built an AI that predicts football matches before kickoff — and forces it to stay honest"
}