Emircan Erdemci

Formadaş

Find footballers who played for both clubs.

  • TypeFootball data app
  • Year2026
  • My roleDesign, data pipeline and full stack development

Compare clubs or search by country to explore player careers, available match statistics and shareable profiles. Install it on your phone.

The challenge

Reconcile fragmented club records and multilingual names, while keeping results available when Wikidata is slow or offline.

My role

I built the interface, data pipeline, SQLite cache, scheduled updates and share cards, including Docker deployment.

Architecture

Where each part runs. Red follows the example flow.

  1. L1 Interface Runs on: Browser

    Club and country searches, career pages and sharing. Installable, with light and dark themes.

    • Nuxt 4
    • Nuxt UI 4
    • Installable web app
  2. L2 Edge Runs on: Cloudflare

    Caches pages for ten minutes; clears them after the previous container stops serving.

    • Cloudflare cache
  3. L3 Server Runs on: Docker on an Oracle Cloud VM

    Handles API requests, share cards and scheduled updates with Nitro and Dokploy.

    • Node 24
    • Nitro
    • Docker
    • Dokploy
    • Takumi
  4. L4 Data Runs on: SQLite on a Docker volume

    Persistent results, profiles and a player index covering 150 clubs.

    • SQLite
    • Result cache
    • Local player index
  5. L5 External services Runs on: Wikidata

    Career records and available statistics through SPARQL; photos from Wikimedia Commons.

    • Wikidata SPARQL
    • Wikimedia Commons

Step by step: Who played for Beşiktaş and Galatasaray?

  1. L1 · Interface Two clubs are selected; /api/common-players receives the request.
  2. L3 · Server Related Wikidata club entries are grouped.
  3. L4 · Data SQLite serves cached results, refreshing expired entries in the background.
  4. L5 · External services On a cache miss, SPARQL fetches players and career records.
  5. L3 · Server Names and spells are merged; players receive a 0 to 100 score.
  6. L1 · Interface Results appear; a local index covers Wikidata outages.

Key decisions

  1. 01

    Background refresh

    Freshness lasts one day during transfer periods, one week otherwise. Expired results are served while refreshing.

  2. 02

    Scheduled updates

    Overnight refreshes run daily during transfer periods and weekly otherwise.

  3. 03

    Club aliases

    Alias groups combine football teams and multi-sport parent records before querying.

  4. 04

    Name matching

    Turkish and English names use normalisation, initials and Jaro-Winkler matching. Single-word names require an exact normalised match.

  5. 05

    Share cards

    Takumi renders 1200×630 cards in about 40 ms in recorded tests. Images remain cached until profiles change.

  6. 06

    Deployment cache

    Cloudflare’s cache is cleared after the old container stops serving, reducing references to outdated scripts.

Desktop and mobile

Next project · 04 InspireIT A bilingual corporate website built with WordPress.
Contact

Let's talk.

Email me about your next web project.

Email me emircan.erdemci@hotmail.com