Case / hyperlocal data hub

Kommunfotbollen

Next.js / Claude API / GitHub Actions

Kommunfotbollen aggregates standings, matches, and news for a town's football teams in one place, kept automatically up to date without anyone entering data by hand.

Problem

Local football coverage was scattered across an external sports data source and several local newspapers. No single place aggregated leagues, matches, and goal scorers, and match reports existed only as unstructured free text.

Solution

I built a Next.js app with a source-agnostic ingest architecture that pulls leagues and matches, and an AI pipeline where Claude reads local newspaper match reports, judges whether an article is relevant to a given team, and extracts goal scorers from the unstructured text.

Technical decisions
Source-agnostic ingest architecture (MatchSource) so more data sources can be added without rewriting the rest of the app.Claude handles two separate AI tasks: news relevance filtering and goal-scorer extraction from match reports.Supabase Postgres via Drizzle instead of an embedded database, so data survives restarts independent of where the app runs.Sync moved from in-process timers to a scheduled GitHub Actions cron hitting an authenticated endpoint, keeping operations simple and stateless.Zod validation of external data to keep the data model reliable despite sources of varying quality.
What it shows

The project shows that I can build integrations against multiple external data sources, use AI for structured extraction from text, and make deliberate architecture choices to keep operating costs down.

Tech
Next.js 16TypeScriptDrizzle ORMSupabaseZodTailwind v4Anthropic SDKGitHub ActionsRender