Skip to content

Repository files navigation

RESONIX

AI-Powered Global Music Discovery Engine

Discover music by mood, emotion, era, weather, or plain English β€” across every language, genre, and decade.

Next.js TypeScript Tailwind CSS Supabase Gemini Vercel


What is Resonix?

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.


Features

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

Architecture

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
Loading

Data Flow β€” Search Request

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[] }
Loading

Page & Route Map

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
Loading

Project Structure

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

Tech Stack

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

Getting Started

Prerequisites

Local Setup

# 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

Environment Variables

# 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:3000

Note: Never commit .env.local. It is already listed in .gitignore.


Resilience & Edge Case Handling

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

Accessibility & Performance

  • Reduced Motion β€” All animations check useReducedMotion() from motion/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 --noEmit exits 0. No type suppressions or any casts in production paths.

API Routes Reference

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

Design System

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

License

MIT Β© 2025 Saatvik Gupta


Built with Next.js Β· Powered by Gemini Β· Deployed on Vercel

About

AI-powered global music discovery engine using semantic, mood, and activity curation.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages