Skip to content

raihanCarder/MusicForYou

Repository files navigation

🎡 Music4You

The album diary for people with real opinions.

Music4You is a Letterboxd-style music web app where you rate albums, pin favourite records to your public profile, and follow a daily editorial pick. Built as a full-stack Next.js project with a clean provider/database architecture ready for Spotify and Supabase at scale.


🌱 App Features

  • 🌟 Rate albums 1–10 and have your score contribute to a community average.
  • ❀️ Pick four favourite albums directly from album pages, with replacement flow when your profile is already full.
  • πŸ‘€ Build a public music identity β€” custom display name, bio, avatar, and a shareable /u/[username] profile showing your four favourite albums and four most recent ratings.
  • πŸ“… Album of the Day β€” one record gets the spotlight for the full day, then moves to an archive that never repeats until the catalog runs out.
  • πŸ” Discovery feed β€” a curated grid of albums to explore, backed by a swappable provider interface.
  • πŸ” Authentication β€” sign up, sign in, sign out via Supabase Auth with route-level middleware that keeps auth pages clean for signed-in users.
  • βš™οΈ Settings page β€” view and edit your profile, including avatar randomization.

πŸ› οΈ Tech Stack

Layer Technology
Framework Next.js 15 (App Router)
UI MUI v7 + Tailwind CSS v4
Language TypeScript
Auth + DB Supabase (Auth, Postgres, RLS)
Notifications react-hot-toast
Runtime React 19 (Server + Client Components)

πŸ—οΈ Architecture

Interface-driven data layer

Two core interfaces keep the app decoupled from any specific vendor:

MusicProvider   β€” search albums, fetch album details, get featured albums
AlbumDatabase   β€” persist albums, manage featured lists, drive the daily rotation

Swapping from mock data to Spotify, or from Supabase to another database, means writing a new adapter β€” not touching UI code.

Request flow

Page (Server Component)
  └── MusicService          cache-first orchestrator
        β”œβ”€β”€ MusicProvider   fetch from external API (Spotify / mock)
        └── AlbumDatabase   read/write Supabase (Supabase.ts)

Auth flow

Middleware (proxy.ts)       redirect signed-in users away from /signin, /signup
  └── getUser()             server-only Supabase session check
        β”œβ”€β”€ Server pages    redirect to /signin if not authenticated
        └── Server actions  validate session before any mutation

πŸ“ Project Structure

src/
β”œβ”€β”€ app/                          # Next.js App Router routes
β”‚   β”œβ”€β”€ page.tsx                  # Landing page
β”‚   β”œβ”€β”€ layout.tsx                # Root layout (Nav + Footer)
β”‚   β”œβ”€β”€ providers.tsx             # MUI theme + toast provider (client boundary)
β”‚   β”œβ”€β”€ feed/                     # Discovery album grid
β”‚   β”œβ”€β”€ album/[id]/               # Dynamic album detail + rating page
β”‚   β”œβ”€β”€ album-of-the-day/         # Daily editorial page
β”‚   β”œβ”€β”€ profile/                  # Authenticated user profile (editable)
β”‚   β”œβ”€β”€ u/[username]/             # Public profile by username
β”‚   β”œβ”€β”€ settings/                 # Account settings
β”‚   β”œβ”€β”€ signin/                   # Sign-in form + server action
β”‚   └── signup/                   # Sign-up form + server action
β”‚
β”œβ”€β”€ components/                   # Shared UI components
β”‚   β”œβ”€β”€ daily/                    # Daily album page sub-components
β”‚   β”‚   β”œβ”€β”€ DailyAlbumHero.tsx    # Cover, title, stats, CTAs
β”‚   β”‚   β”œβ”€β”€ DailyTrackSpotlight.tsx  # Track listing panel
β”‚   β”‚   β”œβ”€β”€ DailyArchive.tsx      # Previous picks grid
β”‚   β”‚   └── DailyRightColumn.tsx  # Scoreboard + ritual info
β”‚   β”œβ”€β”€ Nav.tsx                   # Server nav shell with streaming auth slot
β”‚   β”œβ”€β”€ NavClient.tsx             # Client nav with logo + links
β”‚   β”œβ”€β”€ PageFooter.tsx            # Sitewide footer with links + contact
β”‚   β”œβ”€β”€ AlbumCard.tsx             # Album cover card
β”‚   β”œβ”€β”€ AlbumGrid.tsx             # Responsive album grid layout
β”‚   β”œβ”€β”€ AlbumView.tsx             # Full album detail view
β”‚   β”œβ”€β”€ AlbumFavoriteSection.tsx  # Favourite toggle + replacement flow
β”‚   β”œβ”€β”€ AlbumRatingSection.tsx    # Rating form + community score display
β”‚   β”œβ”€β”€ FavoriteReplaceDialog.tsx # Choose which favourite album to swap out
β”‚   β”œβ”€β”€ SongView.tsx              # Individual track row
β”‚   β”œβ”€β”€ DailyAlbumPageView.tsx    # Orchestrator for daily page sections
β”‚   β”œβ”€β”€ ProfilePageView.tsx       # User profile layout
β”‚   β”œβ”€β”€ ProfileAvatar.tsx         # Avatar with initials fallback
β”‚   └── ProfileEditDialog.tsx     # Edit profile dialog
β”‚
β”œβ”€β”€ actions/                      # Next.js Server Actions
β”‚   β”œβ”€β”€ users.ts                  # Sign up, sign in, sign out
β”‚   β”œβ”€β”€ favorites.ts              # Add/remove/replace profile favourites
β”‚   β”œβ”€β”€ profiles.ts               # Update profile
β”‚   └── reviews.ts                # Submit album rating
β”‚
β”œβ”€β”€ auth/                         # Supabase client factories
β”‚   β”œβ”€β”€ server.ts                 # SSR-aware server client + session helpers
β”‚   β”œβ”€β”€ client.ts                 # Browser client
β”‚   β”œβ”€β”€ admin.ts                  # Service-role admin client (server-only)
β”‚   └── env.ts                    # Environment variable validation
β”‚
β”œβ”€β”€ lib/
β”‚   β”œβ”€β”€ db/
β”‚   β”‚   └── errors.ts             # Shared DB error utilities (unique violation, etc.)
β”‚   β”œβ”€β”€ favorites/
β”‚   β”‚   β”œβ”€β”€ types.ts              # Favourite album domain types
β”‚   β”‚   └── server.ts             # Favourite fetch + mutation helpers
β”‚   β”œβ”€β”€ music/
β”‚   β”‚   β”œβ”€β”€ types.ts              # Core contracts: AlbumData, MusicProvider, AlbumDatabase
β”‚   β”‚   β”œβ”€β”€ Music.ts              # MusicService factory (singleton)
β”‚   β”‚   β”œβ”€β”€ MusicService.ts       # Cache-first orchestrator for all music data
β”‚   β”‚   β”œβ”€β”€ Supabase.ts           # AlbumDatabase implementation
β”‚   β”‚   β”œβ”€β”€ server.ts             # Shared album-row persistence helpers for mutations
β”‚   β”‚   β”œβ”€β”€ mappers.ts            # DB row ↔ domain type transformations
β”‚   β”‚   β”œβ”€β”€ supabaseQueries.ts    # Low-level Supabase query builders
β”‚   β”‚   β”œβ”€β”€ dailyAlbum.ts         # Date/time utilities for daily rotation
β”‚   β”‚   β”œβ”€β”€ discovery.ts          # Cached discovery feed helpers
β”‚   β”‚   β”œβ”€β”€ constants.ts          # Shared slug/limit constants
β”‚   β”‚   β”œβ”€β”€ Spotify.ts            # Spotify provider stub (in progress)
β”‚   β”‚   └── testing/              # Mock provider + seeded album data
β”‚   β”œβ”€β”€ profiles/
β”‚   β”‚   β”œβ”€β”€ types.ts              # Profile domain types
β”‚   β”‚   β”œβ”€β”€ server.ts             # Profile fetch, create, update (server-only)
β”‚   β”‚   β”œβ”€β”€ format.ts             # Date/display formatting for profiles
β”‚   β”‚   β”œβ”€β”€ avatar.ts             # DiceBear avatar URL generation
β”‚   β”‚   └── validation.ts         # Username rules + profile input validation
β”‚   └── reviews/
β”‚       β”œβ”€β”€ types.ts              # Rating domain types
β”‚       └── server.ts             # Rating fetch + upsert (server-only)
β”‚
└── proxy.ts                      # Middleware: auth redirects

πŸ—„οΈ Database Schema

Table Purpose
profiles User profile data (username, display name, bio, avatar)
albums Persisted album records with provider metadata
reviews User ratings (1–10) per album
profile_favorite_albums Up to four public favourite albums per user
featured_lists Named curated lists (feed, daily rotation)
featured_list_items Albums assigned to a list with rank

βš™οΈ Local Setup

1. πŸ“¦ Install dependencies

npm install

2. πŸ”‘ Configure environment variables

cp .env.example .env.local

Required:

NEXT_PUBLIC_SUPABASE_URL
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY
SUPABASE_SERVICE_ROLE_KEY

3. 🐳 Start local Supabase (Docker required)

npm run supabase:start

Reset to a clean database from migrations:

npm run supabase:db:reset

If you are connected to a hosted Supabase project, push new migrations after schema changes:

npm run supabase:db:push

4. ▢️ Run the dev server

npm run dev

Open http://localhost:3000.


πŸ“œ Scripts

Command Description
npm run dev Start local dev server
npm run build Production build
npm run start Run production build
npm run lint Lint project
npm run supabase:start Start local Supabase stack
npm run supabase:stop Stop local Supabase stack
npm run supabase:status Print local Supabase URLs and keys
npm run supabase:db:reset Rebuild local DB from repo migrations
npm run supabase:db:push Push local migrations to hosted Supabase
npm run supabase:migration:new -- <name> Create a new migration file

πŸ—ƒοΈ Database Workflow

Migrations live in supabase/migrations β€” the repo is the source of truth, not the dashboard. Use the dashboard for logs, data inspection, and auth settings only.

When you pull code that adds a new schema-backed feature, make sure the matching migration has been applied before testing the UI. For this favourites feature, that means 20260412000000_profile_favorite_albums.sql must exist in the target database or the app will fail when it queries profile_favorite_albums.

# Create a new migration
npm run supabase:migration:new -- add_playlists

# Apply full history locally
npm run supabase:db:reset

# Link to hosted project once
npx supabase link --project-ref <your-project-ref>

# Push to hosted project
npm run supabase:db:push

πŸ›£οΈ Roadmap

  • πŸ”Ž Wire nav search to MusicService.searchAlbums
  • 🎧 Complete Spotify provider implementation
  • 🀝 Friends / social graph
  • πŸ“‹ Album lists and year-in-review summaries
  • πŸ† Ratings connected to daily scoreboard

πŸ’‘ Why This Project

Music4You demonstrates product-quality full-stack engineering:

  • 🧱 Server/client boundary discipline β€” data fetching and mutations stay on the server; the client only handles interactivity.
  • πŸ”Œ Interface-driven architecture β€” MusicProvider and AlbumDatabase are contracts, not implementations. Spotify and any future database are drop-in replacements.
  • 🧩 Modular codebase β€” domain logic (music, profiles, reviews) is isolated in lib/, shared utilities (db/errors, music/mappers) prevent duplication, and large components are split into focused sub-components.
  • πŸ” Auth done right β€” SSR-aware Supabase clients, service-role admin isolation, and middleware-level redirect guards.
  • 🎯 Product thinking β€” discovery feed, shareable profiles, and a daily editorial feature that creates a reason to return every day.

Built by Raihan Carder 🎢

About

Music4You - Rate your favourite things in Music!

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors