←

wnur website

wnur cat stack animation

overview

new website for wnur 89.3 fm, northwestern's student-run radio station. it's live at wnur.org, go hit listen. the old site didn't really match what wnur is, but this one does: station branding, a listen bar that follows you around, live on-air info, and an ascii visualizer that reacts to the broadcast in real time. bass hits move the field, mids warp it, treble adds detail.

it has also grown past a listen page. djs log sets from their own accounts, listeners can browse and search playlists, and wavelength editors publish from the same site. built with others from the 2026-2027 exec board. i led website development and design, and i am wavelength lead.

features

  • ascii hero that reads the live stream: open the site, press play, watch the canvas move with whatever's on air
  • global listen bar with play/pause and now-playing context on every page
  • radio and schedule pages with today's lineup and the current show highlighted
  • dj playlist logging during a set, with optional spotify playlist import
  • public recent playlists archive and playlist search
  • wavelength publishing: editors write and update articles in-site, readers get the public magazine
  • sticky header cat logo that animates when you're listening
  • about, contact, news, wavelength, and sports section layouts

playlists and dj tools

approved djs sign in at /dj, wait for station admin approval if they're new, then log tracks at /dj/log while they're on air. they can also pull tracks in from a spotify playlist. listeners don't need an account: they get the archive and search. password resets go through supabase so the email opens the live site, not localhost.

wavelength

wavelength is wnur's publication. editors use a gated workspace at /dj/wavelength to draft and update articles; published pieces live at /wavelength. same login system as the dj tools, different permission gate.

technical details

  • next.js 16 app router, react 19, typescript, tailwind css v4
  • /api/stream: same-origin proxy for the live rcs revma stream so the browser can run web audio analysis without cors issues
  • AudioReactiveCanvas: canvas flow-field visualizer driven by analyser metrics from the stream (production react/typescript version; separate from the vanilla demo on this portfolio site)
  • /api/on-air: schedule data from a google sheet csv export, parsed in chicago time; revalidates every 60 seconds
  • supabase for dj accounts, approvals, playlist logging, and wavelength articles
  • spotify oauth for importing a playlist into the logger
  • /api/contact: contact form email through resend with validation and a honeypot field
  • sticky header with animated cat logo states for idle vs. playing
  • page transitions and reduced-motion fallbacks sitewide

schedule workflow

djs maintain a shared google sheet (day | start | show | dj). the site reads a public csv export url from env, derives now playing and up next, and polls the on-air api from the client. no separate cms or database for the schedule.

related work

the ascii visualizer has its own write-up here: ascii audio interpreter.