Concert Radar
A Spotify-connected concert discovery app that aggregates four ticketing sources and emails you when an artist you follow plays within your radius. MVP shipped — 123 tests passing.
- Next.js 15
- TypeScript (strict)
- Tailwind CSS
- Prisma
- SQLite
- NextAuth v5
- Spotify OAuth
- Vercel Cron
- Resend
- Vitest

01 / Context
Music fans miss concerts by artists they follow because announcements are scattered across Instagram, venue sites, and a handful of separate ticketing platforms. There is no single place to say "tell me when any of my Spotify artists plays within 100km of Bergen." Concert Radar aggregates Ticketmaster, Bandsintown, Songkick, and Billetto — the latter being the dominant Nordic platform — to cover the smaller venues and touring acts that announce on some sources but not others.
02 / My role
I designed and built the whole MVP solo: the Spotify-native visual direction, the dashboard and concert flows, the data model, the multi-source aggregation backend, and the daily notification pipeline. I shipped all 15 planned vertical-slice tasks, then followed up with a v2 redesign and a dedicated mobile port with a bottom tab bar.
03 / Problem
Aggregating four independent APIs creates real engineering problems: the same show appears on multiple sources, free-text artist search produces false positives like "The 1975" matching "1975 Anniversary Concert," and a user with 200 tracked artists hitting four APIs could fire 800 calls at once. On the design side the dashboard had to feel like a native companion to Spotify — rich artist imagery, not a bare table — while staying fast and never emailing the same user about the same concert twice.
04 / Approach
I abstracted every source behind a shared SourceAdapter interface so adapters are independently unit-tested against recorded JSON fixtures, with no live network in CI, and put Songkick and Billetto behind feature flags. Cross-source duplicates collapse to one card with multiple source badges by grouping on (normalized artist, venue city, event date), using diacritic-stripping name normalization and Spotify popularity as a matching confidence signal. A daily Vercel Cron job syncs all users, writes per-source SyncLog rows so one failing source never aborts the run, and sends a Resend digest — with a unique (userId, concertId) constraint guaranteeing no concert is ever emailed twice. Spotify OAuth tokens are AES-256-GCM encrypted at rest behind a custom NextAuth adapter, distances use an inline Haversine, and concert times render in the venue local time zone.
05 / Result
The MVP shipped with 29 of 30 definition-of-done items complete and 123 tests passing across 17 files on a clean production build and 14 routes. It then earned a full v2 redesign — a marketing landing page, a hero-card dashboard, light and dark themes — plus a mobile port. It is my strongest proof of disciplined, test-first engineering paired with a coherent design system.
More screens

