//US — The Music
Collaboration Platform
A place where independent artists upload tracks, discover other artists' music, record vocals or ideas over existing tracks, and connect with collaborators. Built for the Indian indie music scene, starting with Nucleya's album remix contest.
Platform Overview
What //US delivers across web and iOS
//US is a full-stack music collaboration platform with three surfaces: a Next.js web app, a native Swift iOS app, and an Express backend API. All three share a single PostgreSQL database and Cloudflare R2 storage layer.
🎵 Upload & Share Tracks
Artists upload original music (MP3, WAV, FLAC up to 100MB), set genre/BPM/key metadata, and publish to the community.
🎧 Discover & Play
Browse a feed of public tracks with genre filters, waveform visualization, and a persistent mini-player for continuous listening.
🎤 Record Collaborations
Listen to any track and record your own take over it — vocals, rap, instruments — directly in the browser or iOS app.
💬 Real-time Messaging
Socket.io powered chat with text, voice notes, and file sharing. Start conversations from any track or profile.
🏆 Remix Contests (NEW)
Artists create time-bound remix projects. Community submits remixes. Owner reviews and selects winners for official releases.
👤 Artist Profiles
Each artist has a public profile with bio, genres, skills, tracks, collaboration count, and follow/unfollow.
Authentication
Three auth methods across web and iOS
- Register: POST /api/auth/register — email, password (min 8 chars), name, optional artistName
- Login: POST /api/auth/login — returns JWT access token (15 min) + httpOnly refresh cookie (7 days)
- Refresh: POST /api/auth/refresh — token rotation, issues new access token + rotated refresh cookie
- Rate limited: 10 requests per 15 minutes on auth endpoints
User clicks "Continue with Google"
Redirects to GET /api/auth/google which triggers Passport Google strategy
Google consent screen
Scope: profile + email. Published OAuth app, no test user restriction.
Callback at /api/auth/google/callback
Find-or-create user by Google profile. Issue JWT + refresh cookie.
Redirect to frontend
Frontend receives ?access_token= URL param, stores in Zustand auth state.
GoogleSignIn SDK opens browser sheet
Uses iOS Client ID. ColabApp.swift handles onOpenURL for redirect.
App receives Google ID token
GoogleAuthService.swift extracts the idToken from GIDSignInResult.
POST /api/auth/google/mobile
Backend verifies token with Google's tokeninfo endpoint, find-or-creates user.
Token stored in Keychain
AuthStore (@Observable) updates isAuthenticated, triggers UI switch from onboarding to main app.
Tracks & Upload
The core content unit of the platform
A Track is the fundamental content object. Artists upload audio, set metadata, and publish. Tracks are what people discover, play, and record collaborations over.
| Field | Type | Notes |
|---|---|---|
| title | String | Required |
| description | String? | Optional, shown on track detail |
| genre | String? | e.g. "Electronic", "Hip Hop" |
| bpm | Int? | Beats per minute |
| key | String? | Musical key, e.g. "Am", "C#" |
| tags | String[] | Freeform tags |
| lookingFor | String[] | e.g. ["vocalist", "rapper", "guitarist"] |
| visibility | Enum | PUBLIC / PRIVATE / UNLISTED |
| stemsAvailable | Boolean | Whether stems can be downloaded |
| downloadable | Boolean | Whether the full track can be downloaded |
Request presigned URL
POST /api/uploads/presign with fileName, fileType, fileSize (max 100MB). Accepts MP3, WAV, M4A, AAC, OGG, FLAC, WebM.
Direct upload to R2
Client PUTs file directly to Cloudflare R2 using the presigned URL. No server bandwidth used.
Complete upload
POST /api/uploads/complete with key + trackId. Sets audioUrl, status to "processing".
Waveform generation
BullMQ job runs audiowaveform to generate peak data. Track status moves to "ready" when done.
↓
error
Only tracks with status "ready" appear in public feeds.
Discover & Search
Finding tracks and artists
Home Feed (/home)
Infinite scroll of public tracks with genre filters. Each card shows waveform bars, artist avatar, play count, "looking for" tags. Three-dot menu with Copy Link, Share, Report.
Search (/search)
Full-text search across artists + tracks. Filter by type (artists / tracks / all). Searches name, artistName, genres, skills, title, tags, description via ILIKE + array contains.
Dashboard (/dashboard)
Artist's own stats: track count, collaboration count, recent activity. Quick actions: upload, record, browse.
Mini Player
Persistent glassmorphism audio player (desktop). Stays visible while browsing. Shuffle/skip/repeat buttons (currently no-ops, future feature).
Record & Collaborate
The core collaboration mechanic
This is the signature feature of //US. A user finds a track they like, and can immediately record their own take over it — vocals, rap, beats, instruments — all within the app.
User opens track detail page
Sees waveform player, track metadata, existing collaborations, and a prominent "Record" CTA button.
Navigates to /record/[trackId]
In-app recording interface loads. Reference track is queued up for playback alongside recording.
Records their take
LiveWaveform component shows real-time audio visualization. User can play the reference track while recording their part on top.
Upload recording
Same presigned URL flow as track upload. Audio is stored in R2. POST /api/recordings creates the recording with optional note.
Recording appears on track page
Shows up in the "Collaborations" section of the track detail page with the recorder's profile and playback.
Messaging
Real-time chat between collaborators
Inbox (/inbox)
List of all conversations with last message preview, unread count, and other participant info. Ordered by most recent activity.
Chat Thread (/chat/[id])
Full conversation view with cursor-based pagination (30 messages per page, max 100). Real-time delivery via Socket.io.
Message Types
TEXT — standard text messages. AUDIO — voice notes with duration. FILE — file sharing with original filename.
Conversation Starters
Start conversations from: track detail page ("Message" button), artist profile page, or directly from inbox. Can optionally link a track to the conversation for context.
Profiles & Social
Artist identity and social graph
- name — Display name (required)
- artistName — Unique handle, case-insensitive (used in URLs)
- avatar — Profile picture (R2 CDN URL)
- bio — Free text description
- location — City / area
- genres — Array of genres (e.g. ["Electronic", "Hip Hop"])
- skills — Array of skills (e.g. ["Producer", "Vocalist", "Guitarist"])
- isVerified — Verification badge (admin-set)
Every profile shows four stats:
- trackCount — Number of published tracks
- collabCount — Number of recordings made
- followerCount — People following this artist
- followingCount — People this artist follows
- Follow / Unfollow — Idempotent toggle. Paginated follower/following lists.
- Message — Button on profile creates/opens a conversation
- Share Profile — Copy profile link (working)
- Edit Profile — Button exists but edit flow not yet built (planned)
Project / Contest System
The new headline feature — remix contests
Core concept: A Project is a container that holds reference tracks (the originals to remix), a deadline, and collects submissions from the community. The project owner reviews all submissions and can shortlist or select winners.
DRAFT
Project is being set up. Owner adds title, description, cover art, deadline, reference tracks. Not visible to the public.
OPEN
Project is live and accepting submissions. Visible on the projects browse page. Users can listen to reference tracks and submit remixes.
REVIEWING
Deadline has passed (or owner manually closed submissions). Owner reviews all submissions, shortlists favorites, selects winners.
CLOSED
Winners selected. Owner sets release title, date, and streaming URL. Project becomes an archive of the contest.
| Field | Type | Purpose |
|---|---|---|
| title | String | e.g. "Remix Nucleya's New Album" |
| description | String? | Rules, what the artist is looking for, prizes |
| coverUrl | String? | Project artwork / album cover |
| deadline | DateTime? | Submission cutoff date |
| status | Enum | DRAFT / OPEN / REVIEWING / CLOSED |
| maxSubmissions | Int? | Per-user submission cap (null = unlimited) |
| releaseTitle | String? | Final album/EP name (set when closing) |
| releaseDate | DateTime? | When the final release drops |
| releaseUrl | String? | Link to streaming platforms |
| Field | Type | Purpose |
|---|---|---|
| audioUrl | String | R2 CDN URL of the remix |
| waveformData | Json? | Peak data for visualization |
| duration | Float? | Length in seconds |
| note | String? | Submitter's message to the owner |
| feedback | String? | Owner's private notes (never shown to submitter) |
| status | Enum | PENDING / SHORTLISTED / SELECTED / REJECTED |
| referenceTrackId | String? | Which reference track this remixes |
A project contains one or more reference tracks — these are existing Track objects that the owner attaches to the project. They're the "originals" that people will remix.
- Reference tracks have an order field for display ordering
- A track can only be added once per project (unique constraint)
- Owner can add, remove, and reorder reference tracks
- Submitters can optionally tag their submission to a specific reference track
Project User Flows
End-to-end journeys for creators and submitters
Flow A: Artist Creates a Project
Navigate to /project/new
Only visible to users with ARTIST or ADMIN role. At launch, only Nucleya has this access.
Fill project details
Title, description (rules, what they're looking for), cover art upload, deadline picker, max submissions per user.
Attach reference tracks
Search/select from their own existing tracks. Drag to reorder. These become the tracks people will remix.
Save as draft or publish
Draft saves without making it public. Publish moves status to OPEN and the project appears in /projects.
Flow B: User Discovers & Submits a Remix
Browse /projects or see featured banner on /home
Active projects appear as prominent cards with cover art, title, deadline countdown, and submission count.
Open project detail (/project/[id])
See full description, all reference tracks with inline waveform players, existing submissions gallery.
Listen to reference tracks
Play each reference track to find one they want to remix. Each track has full waveform visualization.
Click "Submit Your Remix"
Navigates to /project/[id]/submit. Button disabled if: not logged in, deadline passed, or maxSubmissions reached.
Upload remix audio
Same presigned URL upload flow as regular track upload. Select which reference track they remixed (optional). Add a note to the artist.
Preview and submit
Listen to uploaded audio before final submission. Success screen links back to the project page.
Owner Review Dashboard
/project/[id]/manage — the curation interface
The owner review dashboard is where the project creator reviews all submissions, shortlists favorites, and selects winners for the official release. Only accessible by the project owner.
Stats Bar
Top of the page shows: total submissions, pending count, shortlisted count, selected count. Quick visual overview of review progress.
Filter & Browse
Filter submissions by status: All / Pending / Shortlisted / Selected. Each card shows user info, inline audio player, note, timestamp.
Review Actions
Per-submission buttons: Shortlist / Select / Reject. Private feedback text field for owner's notes (never shown to submitter).
Project Controls
Close submissions (OPEN → REVIEWING). Reopen if needed. Finalize once winners are selected.
Release Panel
When moving to CLOSED: set release title (album/EP name), release date, and streaming platform URL. This info shows on the project page.
Browse pending submissions
Listen to each remix with inline player. Read submitter's note.
Shortlist promising ones
Click "Shortlist" to flag interesting submissions. Add private feedback notes.
Select winners from shortlist
Review shortlisted submissions. Click "Select" on the final picks for the album.
Finalize the project
Set release title, date, and streaming URL. Project moves to CLOSED. Selected submissions are featured.
Roles & Access Control
Phased rollout strategy
| Role | Can Create Projects | Can Submit Remixes | Can Browse/Play | Notes |
|---|---|---|---|---|
| USER (default) | No | Yes | Yes | Standard user — discovers, plays, records, submits |
| ARTIST | Yes | Yes | Yes | Can create and manage projects. Nucleya at launch. |
| ADMIN | Yes | Yes | Yes | Full platform access. For the //US team. |
Phased Rollout Plan
- Nucleya's account set to ARTIST role via DB update
- Only ARTIST/ADMIN roles can access POST /api/projects
- Nucleya creates the first project: "Remix my new album"
- Community signs up, browses reference tracks, submits remixes
- Nucleya reviews submissions and selects winners for the release
- Goal: Prove the concept with real content and real users
- Add "Request Artist Status" flow for verified users
- Any approved artist can create their own remix projects
- Project discovery page becomes a marketplace of active contests
- Home feed shows projects alongside individual tracks
All Pages & Routes
Complete route map across web and iOS
Web (Next.js App Router)
| Route | Status | Purpose |
|---|---|---|
| / | Live | Root redirect to /dashboard |
| /onboarding | Live | Sign-up flow (Google + email) |
| /login | Live | Login page |
| /dashboard | Live | Artist stats, quick actions |
| /home | Live | Discover feed with filters |
| /search | Live | Artist + track search |
| /track/[id] | Live | Track detail, waveform, collaborations |
| /record/[trackId] | Live | In-app recording interface |
| /upload | Live | Track upload with R2 presigned URLs |
| /profile | Live | Own profile, share, logout |
| /profile/[id] | Live | Other artist's profile |
| /inbox | Live | Conversation list |
| /chat/[id] | Live | Real-time messaging thread |
| /projects | New | Browse open projects/contests |
| /project/[id] | New | Project detail + reference tracks + submissions |
| /project/[id]/submit | New | Upload remix to project |
| /project/[id]/manage | New | Owner review dashboard |
| /project/new | New | Create project (ARTIST/ADMIN only) |
| /project/[id]/edit | New | Edit project metadata |
| /settings | Planned | Account settings, change password |
iOS (SwiftUI)
| View | Status | Purpose |
|---|---|---|
| OnboardingView | Live | Login / sign-up landing |
| HomeFeedView | Live | Track feed with filters |
| SearchView | Live | Full-text search |
| DashboardView | Live | User stats |
| TrackDetailView | Live | Track page + recordings |
| UploadTrackView | Live | Track upload |
| RecorderView | Live | Record over a track |
| MyProfileView | Live | Own profile |
| ArtistProfileView | Live | Other artist profiles |
| InboxView | Live | Conversations list |
| ChatThreadView | Live | Chat messages |
| ProjectsListView | New | Browse open projects |
| ProjectDetailView | New | Project detail + submissions |
| SubmitRemixView | New | Upload remix to project |
| ManageProjectView | New | Owner review (ARTIST only) |
| CreateProjectView | New | Create project (ARTIST only) |
Data Model
All Prisma models — existing + new
| Model | Status | Key Fields | Relations |
|---|---|---|---|
| User | Existing | email, name, artistName, avatar, bio, genres[], skills[], role (NEW) | tracks, recordings, conversations, followers, following, projects, submissions |
| Track | Existing | title, audioUrl, waveformData, genre, bpm, key, tags[], visibility, status | user, recordings, projectTracks, submissionRefs |
| Recording | Existing | audioUrl, waveformData, duration, note | track, user |
| Conversation | Existing | lastMessageAt, trackId (optional) | messages, participants, track |
| Message | Existing | type (TEXT/AUDIO/FILE), content, audioUrl, fileUrl | conversation, sender |
| Follow | Existing | followerId, followingId | follower (User), following (User) |
| RefreshToken | Existing | token (hashed), expiresAt | user |
| Project | New | title, description, coverUrl, deadline, status, maxSubmissions, releaseTitle/Date/Url | owner (User), referenceTracks (ProjectTrack[]), submissions |
| ProjectTrack | New | order | project, track |
| Submission | New | audioUrl, waveformData, duration, note, feedback, status | project, user, referenceTrack (Track) |
API Endpoints
Complete endpoint reference
POST /api/auth/login — Get tokens
POST /api/auth/refresh — Rotate refresh token
POST /api/auth/logout — Clear tokens
GET /api/auth/me — Current user profile
GET /api/auth/google/callback — Handle Google callback
POST /api/auth/google/mobile — iOS native token exchange
GET /api/tracks — List tracks (paginated, filtered)
GET /api/tracks/:id — Get single track
PUT /api/tracks/:id — Update track metadata
DELETE /api/tracks/:id — Delete track
GET /api/tracks/:trackId/recordings — List recordings for track
GET /api/conversations — List conversations
GET /api/conversations/:id/messages — Get messages (cursor-based)
POST /api/conversations/:id/messages — Send message
POST /api/conversations/:id/read — Mark as read
PUT /api/profiles/me — Update profile
GET /api/profiles/:artistName — Public artist profile
DELETE /api/follow/:userId — Unfollow
GET /api/profiles/:artistName/followers — Follower list
GET /api/profiles/:artistName/following — Following list
POST /api/uploads/file — Local file upload (dev)
POST /api/uploads/complete — Finalize upload + trigger waveform
POST /api/projects — Create project (ARTIST/ADMIN)
GET /api/projects — List open projects
GET /api/projects/:id — Project detail
PUT /api/projects/:id — Update metadata
DELETE /api/projects/:id — Delete (DRAFT only)
// Lifecycle
POST /api/projects/:id/publish — DRAFT → OPEN
POST /api/projects/:id/close-submissions — OPEN → REVIEWING
POST /api/projects/:id/finalize — REVIEWING → CLOSED
// Reference Tracks
POST /api/projects/:id/tracks — Add reference track(s)
DELETE /api/projects/:id/tracks/:trackId — Remove reference track
PUT /api/projects/:id/tracks/reorder — Reorder tracks
// Submissions
POST /api/projects/:id/submissions — Submit remix
GET /api/projects/:id/submissions — List submissions
GET /api/projects/:id/submissions/mine — My submissions
DELETE /api/projects/:id/submissions/:subId — Withdraw submission
// Owner Review
PUT /api/projects/:id/submissions/:subId/status — Change status
PUT /api/projects/:id/submissions/:subId/feedback — Add private notes
Tech Stack
Infrastructure and tooling
| Layer | Technology | Details |
|---|---|---|
| Web Frontend | Next.js 16.2.2 | App Router, React 19, Tailwind v4, Zustand state |
| Web Backend | Express 5.2.1 | Node 22+, TypeScript 5, Zod validation |
| iOS App | Swift 5.9 / SwiftUI | iOS 17.0+, XcodeGen, SPM packages |
| Database | PostgreSQL + Prisma 7.6 | Custom adapter-pg, generated client |
| Auth | JWT (jose) + Google OAuth | 15min access, 7-day refresh in httpOnly cookie |
| Real-time | Socket.io 4.8.3 | WebSocket for messaging |
| Storage | Cloudflare R2 | S3-compatible, presigned upload URLs |
| Audio Processing | audiowaveform + wavesurfer.js 7 | Server-side peaks, client rendering |
| Job Queue | BullMQ + Redis | Waveform generation jobs |
| Deployment | PM2 + Nginx | VPS at 72.60.201.119, SSL via Certbot |
com.bakebetterapps.colab
Launch Strategy
Nucleya's vision for the initial rollout
Nucleya creates the first Project
Uploads reference tracks from his new album. Sets a deadline. Writes a description explaining what he's looking for in remixes.
Announces on social media
Drives his fanbase to //US. "Sign up, listen to my tracks, upload your remix." Creates initial buzz and user signups.
Community submits remixes
Artists sign up, browse reference tracks, and submit their takes. Platform gets seeded with real content from real musicians.
Nucleya reviews and selects
Uses the owner review dashboard to listen to submissions, shortlist favorites, and select winners for the album.
Album release
Selected remixes get released as an official album. Project is closed with release info (title, date, streaming URL).
Open platform (Phase 2)
After proving the concept, project creation opens to other verified artists. //US becomes the go-to platform for music collaboration in India.
Build Order
Implementation sequence with dependencies
Critical path: Schema → Project API → Submission API → Project Detail Page → Submit Page. Everything else can follow in parallel.
//US Feature Spec v1.0 — Generated 2026-04-08
Based on Nucleya's voice note feedback + existing codebase analysis
Covers: 3 platforms, 20 pages/views, 44 API endpoints, 10 data models