Started with pen and paper to map the core player flow — live indicator, album art, waveform, controls, playlist, mini-bar, and bottom nav — before touching Figma.
Translated to low-fidelity in Figma with layout annotations. Key decision documented here: mini-player bar keeps the live stream persistent while navigating.
Dark base with a single electric magenta accent. Fraunces italic for mix titles; JetBrains Mono for metadata. Waveform animation derived from audio data.
Built in React + Next.js with Web Audio API. CSS animations for waveform. LocalStorage persists volume and last track across sessions. No handoff.
Before opening Figma, the core screen hierarchy was mapped by hand. The wireframe captures every structural decision: where the live badge sits, how the waveform connects to playback state, how the playlist scrolls without interrupting the mini-player.
The annotations aren't decoration — they're the thinking. Each redline communicates intent to the engineer. Since I'm both, it's a contract I write to myself: design what can ship, ship what was designed.
The production playlist view maps directly to the wireframe's track list structure. Track art, track numbering, artist metadata, sort controls, and a "Play All" action — all derived from the original sketch, nothing invented at the code stage.
Dark purple-black base with magenta accent keeps the UI rooted in club culture without sacrificing legibility. Every text element passes WCAG AA contrast.
Every version was a deliberate response to a specific problem — not a cosmetic refresh. Here's what changed and why.
V1 used a circular text badge ("Jersey Club Radio · 24/7") as the player art. During early user validation, feedback revealed users had no immediate visual anchor for the brand and felt it lacked authenticity. In V2, the gradient clover logo replaced it entirely, giving the player a strong, recognisable identity. This iteration improved visual hierarchy, gave the player area more breathing room, and established trust with the core audience.
V2 mobile had the logo upgrade but failed a key usability test: it felt static. Users couldn't immediately tell if audio was actually playing or buffering. V3 introduced three critical additions driven by this feedback: an animated waveform that pulses with the stream, a persistent mini-player bar that locks to the bottom so music never stops during navigation, and a clear progress indicator. These weren't just aesthetic choices — they directly solved the core UX problem of ambiguous system status.
The desktop layout introduced a full sidebar navigation (Radio, New Releases, Search, Queue, My Crate, Chat, Dance Videos, Merch, Game Hub) and a dual-panel layout — playlist on the left, Top Songs / Global Reach charts on the right. This architecture was mobile-first in planning but desktop-first in complexity. Every nav item was validated against real user behaviour from the Beta: what were listeners actually trying to do beyond just hitting play?
The mobile player and desktop dashboard — built from the same wireframe, designed for two contexts. Click the thumbnails to switch screens.
Mobile · Player view
METHODOLOGY
In collaboration with the marketing and growth team, we instrumented the platform with real-time listener tracking — capturing geographic distribution, session depth, and engagement patterns. The data was reviewed weekly and directly informed prioritization decisions across the product roadmap.
LISTENER HEATMAP · GEOGRAPHIC CONCENTRATION
Heatmap data confirmed the primary listener base is concentrated in the US Northeast corridor — New Jersey, New York, and Philadelphia — aligning directly with Jersey Club music's cultural roots. This validated prioritizing English-first UI copy, EST-aligned stream scheduling, and mobile-first layout given the commuter audience profile.
GLOBAL REACH TAB · LIVE ANALYTICS FEATURE
Research revealed DJs and promoters were asking "who's actually listening?" We designed the Global Reach tab as a real-time dashboard — showing active visitors, countries reached, and live listener count — giving artists visibility into their growing footprint. This feature directly addressed DJ retention, making them more likely to promote the platform to their audiences.
KEY RESEARCH FINDINGS
TOP SONGS COMPONENT · DATA-DRIVEN DESIGN
Play-count analytics showed listeners were repeatedly returning to the same tracks — particularly DJ Sliink and DJ Jayhood edits. Rather than surfacing this data only in internal dashboards, the growth team recommended exposing it directly in the UI as a social signal.
The Top Songs ranked list was designed as a lightweight, scannable component: track name, artist, and rank number — no album art, no noise. The ranking updates dynamically based on weekly play data, creating a leaderboard mechanic that incentivizes DJs to submit exclusives.
Top Songs · weekly play-count ranking
I faced a classic engineering vs design tradeoff: building a persistent mini-player is technically complex in React compared to a simple per-page player. However, user research showed listeners heavily navigate mid-song. I chose to build the complex persistent player because the user's continuous listening experience must outweigh development ease.
The circular art rotates while playing — a direct vinyl metaphor. CSS animation-play-state toggles between running and paused based on play state. Adds life with zero JavaScript overhead.
Instead of designing one-off screens, I built a cohesive design system. Reusable components (player bar, track list cards, navigation icons, and buttons) were established as master components in Figma and carried over 1:1 to React. This atomic approach ensured consistency across all viewports.
Accessibility was validated at every step. All text meets or exceeds a 4.5:1 contrast ratio against the dark background. Focus states are fully keyboard-navigable for non-mouse users, and aria-labels are mapped to all interactive player controls. This ensures inclusivity by design.
Fraunces italic for mix titles — expressive, editorial, unexpected in a music context. JetBrains Mono for track metadata — monospaced detail that reads like a setlist. Two distinct voices, one coherent system.
CSS-animated bars simulate a live audio signal. Each bar has a randomized height and staggered delay for an organic, breathing effect. Respects prefers-reduced-motion — animations pause for users who opt out.
Return to portfolio
← All work