Discover music by mood, emotion, era, weather, or plain English β across every language, genre, and decade.
Resonix is an intent-driven music discovery platform designed to combat choice paralysis. Instead of browsing charts or clicking through genre menus, you describe β in plain language, an emoji, a color, even the weather β and Resonix surfaces curated tracks from a 100M+ catalog across every era and language.
It orchestrates four live music APIs and a generative AI model concurrently, synthesizes the results by mood and popularity, and returns recommendations with explanations β not just titles.
| Discovery Mode | Description |
|---|---|
| π Natural Language Search | "Music for a rainy Sunday morning in Tokyo" β full semantic query support |
| π Emoji Search | Translate a sequence of emojis into a mood-matched playlist |
| π¨ Color-Based Discovery | Pick a color; get music that matches its emotional temperature |
| π¦οΈ Weather-Aware Curation | Auto-detects local weather and shifts recommendations accordingly |
| 𧬠Personality Quiz | Short quiz maps your answers to an acoustic profile |
| π Activity Mode | Curates by activity: running, studying, cooking, commuting |
| π€ AI Music Chat | Conversational music assistant β ask follow-up questions about any track |
| πΌ Playlist Generator | Describe a scenario; get a 10-track playlist with a concept blurb |
| π Discovery Wheel | Spin-the-wheel randomised genre exploration |
| π Decade Explorer | Deep-dive any decade from the 1960sβ2020s with an iconic vs. hidden gem comparison slider |
| π Hidden Gems | Surface tracks with <200K lifetime listeners β validated against global indexes |
| βοΈ Artist Comparison | Side-by-side acoustic + mood + stats analysis of two artists, with AI synthesis |
| π Genre Deep-Dive | AI-generated genre explainer with characteristics, essential albums, and underrated picks |
| π§ Music DNA | Animated radar chart profiling your taste: energy, positivity, genre diversity, decades |
| πΊοΈ Taste Map | Interactive scatter map of your musical taste across acoustic dimensions |
| π Lyric Mood Analysis | Classifies track emotional weight without reproducing copyrighted lyrics |
graph TD
User["π€ User Input\n(text Β· emoji Β· color Β· weather)"]
UI["Next.js 16 App Router UI\nZustand Client State"]
Edge["Vercel Edge Router\n/api/* serverless functions"]
Gemini["π€ Gemini 2.5 Flash\nSemantic intent parsing\nStructured JSON output"]
Spotify["π΅ Spotify Web API\n100M+ catalog Β· Acoustic features"]
LastFM["π Last.fm API\nPopularity Β· Tags Β· Similar artists"]
YouTube["βΆοΈ YouTube Data API v3\nCover video links"]
MusicBrainz["π MusicBrainz\nCanonical metadata Β· Cover Art Archive"]
Apple["π Apple Music RSS\nReal-time regional charts"]
Merge["Result Merger\nDeduplicate Β· Re-rank\nPopularity Γ vibe score"]
Cache["Cache Layer\nNext.js fetch cache\nISR + Edge TTL"]
Supabase["ποΈ Supabase\nPostgreSQL + Auth\nUser playlists + sessions"]
User --> UI
UI --> Edge
Edge --> Gemini
Edge --> Spotify
Edge --> LastFM
Edge --> YouTube
Edge --> MusicBrainz
Edge --> Apple
Gemini --> Merge
Spotify --> Merge
LastFM --> Merge
YouTube --> Merge
MusicBrainz --> Merge
Apple --> Merge
Merge --> Cache
Cache --> UI
UI <--> Supabase
sequenceDiagram
participant Browser
participant API as /api/search (Edge)
participant Gemini
participant Spotify
participant LastFM
participant Cache
Browser->>API: POST { query: "rainy Tokyo sunday" }
API->>Gemini: Parse intent β tags, mood, decade (parallel)
API->>Spotify: Search by keywords (parallel)
API->>LastFM: Search by tags (parallel)
Gemini-->>API: { tags, mood, language, era }
Spotify-->>API: Raw track list
LastFM-->>API: Raw track list
API->>Cache: Check Apple Music charts cache
Cache-->>API: Regional trending tracks
API->>API: Merge Β· deduplicate Β· re-rank by vibe + popularity
API-->>Browser: JSON { recommendations[], explanations[] }
graph LR
Home["/ β Landing"]
Search["/search β Results"]
Chat["/chat β AI Chat"]
Playlist["/playlist β Generator"]
Auth["/auth β Login"]
Dashboard["/dashboard"]
DNA["/dashboard/music-dna"]
Map["/dashboard/taste-map"]
Discover["/discover β Hub"]
Wheel["/discover/wheel"]
Decades["/discover/decades"]
Gems["/discover/hidden-gems"]
Compare["/discover/compare"]
Lyric["/discover/lyric-mood"]
Genre["/genre/[genre]"]
Home --> Search
Home --> Chat
Home --> Playlist
Home --> Dashboard
Home --> Discover
Home --> Genre
Dashboard --> DNA
Dashboard --> Map
Discover --> Wheel
Discover --> Decades
Discover --> Gems
Discover --> Compare
Discover --> Lyric
resonix/
βββ src/
β βββ app/
β β βββ page.tsx # Landing / hero
β β βββ search/page.tsx # Search results
β β βββ chat/page.tsx # AI music chat
β β βββ playlist/page.tsx # AI playlist generator
β β βββ auth/page.tsx # Login / signup
β β β
β β βββ dashboard/
β β β βββ page.tsx # User dashboard
β β β βββ music-dna/page.tsx # Radar chart taste profile
β β β βββ taste-map/page.tsx # Scatter map exploration
β β β
β β βββ discover/
β β β βββ page.tsx # Discovery hub
β β β βββ wheel/page.tsx # Spin-the-wheel
β β β βββ decades/page.tsx # Decade explorer + comparison slider
β β β βββ hidden-gems/page.tsx # Under-the-radar tracks
β β β βββ compare/page.tsx # Artist comparison
β β β βββ lyric-mood/page.tsx # Lyric emotional analysis
β β β
β β βββ genre/[genre]/page.tsx # Dynamic genre deep-dive
β β β
β β βββ api/ # Serverless API routes
β β βββ search/route.ts
β β βββ playlist/generate/route.ts
β β βββ trending/route.ts
β β βββ chat/route.ts
β β βββ genre/[genre]/route.ts
β β βββ decades/route.ts
β β βββ hidden-gems/route.ts
β β βββ compare-artists/route.ts
β β βββ lyric-mood/route.ts
β β
β βββ components/
β β βββ layout/
β β β βββ Navbar.tsx
β β β βββ BottomNav.tsx
β β βββ ui/
β β βββ RecommendationCard.tsx
β β βββ MoodSelector.tsx
β β βββ GenreDock.tsx
β β βββ ListenLinks.tsx
β β βββ Letterbox.tsx
β β
β βββ lib/
β β βββ gemini.ts # Gemini client + prompt templates
β β βββ spotify.ts # Spotify OAuth + search
β β βββ lastfm.ts # Last.fm tag + metadata client
β β βββ supabase/ # Supabase SSR + client setup
β β
β βββ store/
β βββ index.ts # Zustand stores (playlists, auth)
β
βββ public/
βββ tailwind.config.ts
βββ next.config.ts
| Layer | Technology | Why |
|---|---|---|
| Framework | Next.js 16 (App Router) | RSC, edge-ready API routes, ISR caching |
| Language | TypeScript 5 | End-to-end type safety; zero runtime type errors |
| Styling | Tailwind CSS 4 | Utility-first; no runtime CSS-in-JS overhead |
| Animations | Motion (Framer Motion v12) | Declarative, performant; respects prefers-reduced-motion |
| Client State | Zustand | Minimal boilerplate; no Provider nesting |
| Auth + DB | Supabase | Cookie-based SSR sessions; PostgreSQL with RLS |
| AI | Google Gemini 2.5 Flash | Fast structured JSON; free tier; context-aware |
| Music Data | Spotify, Last.fm, YouTube, MusicBrainz | Multi-source cross-validation for real recommendations |
| Charts | Apple Music RSS | Real-time regional trending without a paid agreement |
| Data Viz | Recharts | Radar chart for Music DNA profile |
| Deploy | Vercel | Zero-config Next.js; Edge Network; auto-deploys from main |
- Node.js 20+
- A Supabase project (free tier is fine)
- API keys for: Gemini, Spotify, Last.fm, YouTube Data API v3
# 1. Clone
git clone https://github.com/Saatvik-G/Resonix.git
cd Resonix/resonix
# 2. Install dependencies
npm install
# 3. Configure environment
cp .env.example .env.local
# Edit .env.local with your keys
# 4. Run dev server
npm run dev
# β http://localhost:3000# AI
GEMINI_API_KEY=
# Music APIs
LASTFM_API_KEY=
SPOTIFY_CLIENT_ID=
SPOTIFY_CLIENT_SECRET=
YOUTUBE_API_KEY=
# Supabase
NEXT_PUBLIC_SUPABASE_URL=
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=
# App
NEXT_PUBLIC_APP_URL=http://localhost:3000Note: Never commit
.env.local. It is already listed in.gitignore.
| Scenario | Strategy |
|---|---|
| Gemini API timeout / 429 | Promise.race with 1.8s deadline; falls back to Last.fm tag search |
| Spotify auth failure | Stateful circuit breaker β trips for 5 min, prevents thread blocking, drops latency from 22s β 1.2s |
| iTunes cover art timeout | 800ms AbortController abort; falls back to local category placeholder |
| MusicBrainz rate limit | 1.1s request queue built into the fetch layer to prevent API bans |
| Empty / nonsense query | Degrades gracefully to regional trending via Apple Music RSS |
| Duplicate tracks across sources | Deduplicated by normalized title + artist key before ranking |
| Copyrighted lyric reproduction | Prompt directives constrain Gemini to 3β5 word poetic metaphors, never verbatim lyrics |
- Reduced Motion β All animations check
useReducedMotion()frommotion/react. Equalizer bars, rotating records, and splash transitions halt automatically when the OS setting is enabled. - ISR Caching β Genre overviews and decade data use 1-hour ISR; search results are always live.
- Streaming β Long-running AI responses stream progressively to the UI.
- Type Safety β
npx tsc --noEmitexits0. No type suppressions oranycasts in production paths.
| Route | Method | Description |
|---|---|---|
/api/search |
GET |
Semantic multi-source music search |
/api/trending |
GET |
Apple Music regional chart + Last.fm trending |
/api/playlist/generate |
POST |
AI playlist from a natural language prompt |
/api/chat |
POST |
Conversational music AI |
/api/genre/[genre] |
GET |
Genre overview, artists, essential albums, underrated picks |
/api/decades |
GET |
Decade-filtered recommendations |
/api/hidden-gems |
GET |
Tracks with <200K lifetime listeners |
/api/compare-artists |
POST |
Side-by-side artist acoustic + stat analysis |
/api/lyric-mood |
POST |
Lyric emotional classification |
Resonix uses a concert poster / print zine aesthetic β high contrast, no glows, no gradients.
| Token | Value | Usage |
|---|---|---|
| Background | #0b0a0d |
Page background |
| Surface | zinc-950 / zinc-900 |
Cards, inputs, containers |
| Border | zinc-800 |
All dividers and card edges |
| Accent | #fbbf24 (amber-400) |
Active states, icons, highlights |
| Error | rose-900 |
Error borders and labels |
| Display Font | Playfair Display |
Headings (uppercase, bold) |
| Label Font | System monospace | Subheadings, tags, metadata |
| Border Radius | rounded-none |
Everywhere β no rounded corners |
MIT Β© 2025 Saatvik Gupta