Sonic Cloud - Quick Reference Card
Commands
| Command |
Purpose |
npm run dev |
Start development server (port 3000) |
npm run build |
Build production bundle |
npm start |
Start production server |
npm run lint |
Run ESLint code checks |
npx prisma studio |
Open database GUI |
npx prisma migrate dev |
Create and apply migrations |
npx prisma generate |
Regenerate Prisma client |
npx prisma db push |
Push schema to database |
Tech Stack
| Layer |
Technology |
| Language |
TypeScript 5 |
| Framework |
Next.js 16.0.10 (App Router) |
| UI Library |
React 19.2.1 |
| Styling |
Tailwind CSS 4 |
| Database |
SQLite (Prisma ORM 5.22.0) |
| Authentication |
JWT + bcryptjs |
Key Files
| File |
Purpose |
app/layout.tsx |
Root layout with Header, AudioPlayer |
app/page.tsx |
Homepage with trending/new releases |
lib/auth.ts |
JWT utilities (verifyToken, hashPassword) |
lib/db.ts |
Prisma client singleton |
lib/sharing.ts |
Share link generation |
prisma/schema.prisma |
Database schema (10 models) |
types/index.ts |
Core TypeScript types |
project_manifest.json |
Guardrail entity definitions |
Environment Variables
| Variable |
Required |
Purpose |
DATABASE_URL |
Yes |
SQLite file path |
JWT_SECRET |
Yes |
Token signing secret |
NEXT_PUBLIC_API_URL |
Optional |
API base URL |
API Endpoints (40 total)
Authentication
| Method |
Path |
Auth |
Purpose |
| POST |
/api/auth/register |
No |
Register new user |
| POST |
/api/auth/login |
No |
Login and get token |
| POST |
/api/auth/forgot-password |
No |
Request reset token |
| POST |
/api/auth/reset-password |
No |
Reset with token |
Users
| Method |
Path |
Auth |
Purpose |
| GET |
/api/users/me |
Yes |
Get current user |
| PUT |
/api/users/me |
Yes |
Update profile |
Artists
| Method |
Path |
Auth |
Purpose |
| POST |
/api/artists |
Yes |
Create artist |
| GET |
/api/artists/{id} |
No |
Get artist details |
| PUT |
/api/artists/{id} |
Yes |
Update artist (owner) |
| GET |
/api/artists/{id}/songs |
No |
List artist songs |
| GET |
/api/artists/{id}/albums |
No |
List artist albums |
Songs
| Method |
Path |
Auth |
Purpose |
| POST |
/api/songs/upload |
Yes |
Upload song (artist) |
| GET |
/api/songs/{id} |
No |
Get song details |
| PUT |
/api/songs/{id} |
Yes |
Update song (owner) |
| DELETE |
/api/songs/{id} |
Yes |
Delete song (owner) |
| POST |
/api/songs/{id}/play |
No |
Increment play count |
Albums
| Method |
Path |
Auth |
Purpose |
| POST |
/api/albums |
Yes |
Create album (artist) |
| GET |
/api/albums/{id} |
No |
Get album with songs |
| PUT |
/api/albums/{id} |
Yes |
Update album (owner) |
| DELETE |
/api/albums/{id} |
Yes |
Delete album (owner) |
Playlists
| Method |
Path |
Auth |
Purpose |
| GET |
/api/playlists |
Yes |
List user playlists |
| POST |
/api/playlists |
Yes |
Create playlist |
| GET |
/api/playlists/{id} |
No |
Get playlist (respects privacy) |
| PUT |
/api/playlists/{id} |
Yes |
Update playlist (owner) |
| DELETE |
/api/playlists/{id} |
Yes |
Delete playlist (owner) |
| POST |
/api/playlists/{id}/songs |
Yes |
Add song to playlist |
| PUT |
/api/playlists/{id}/reorder |
Yes |
Reorder songs |
Discovery
| Method |
Path |
Auth |
Purpose |
| GET |
/api/discover/trending |
No |
Trending songs (by plays) |
| GET |
/api/discover/new-releases |
No |
Recent songs (by date) |
| GET |
/api/discover/genres |
No |
All genres with counts |
| GET |
/api/discover/genres/{slug} |
No |
Songs by genre |
Labels
| Method |
Path |
Auth |
Purpose |
| POST |
/api/labels |
Yes |
Create label |
| GET |
/api/labels/{id} |
No |
Get label details |
| PUT |
/api/labels/{id} |
Yes |
Update label (owner) |
| GET |
/api/labels/{id}/stats |
No |
Label statistics |
| GET |
/api/labels/{id}/artists |
No |
Label artists |
Search & Sharing
| Method |
Path |
Auth |
Purpose |
| GET |
/api/search |
No |
Search songs/artists/albums |
| POST |
/api/share/song/{id} |
No |
Create song share link |
| POST |
/api/share/playlist/{id} |
No |
Create playlist share link |
| POST |
/api/share/album/{id} |
No |
Create album share link |
| GET |
/api/share/{token} |
No |
Resolve share link |
| POST |
/api/share/{token}/click |
No |
Track share clicks |
Common Patterns
Authentication Flow
// 1. Login → get token
const res = await fetch('/api/auth/login', {
method: 'POST',
body: JSON.stringify({ email, password })
});
const { token } = await res.json();
// 2. Store token
localStorage.setItem('auth_token', token);
// 3. Use in authenticated requests
fetch('/api/users/me', {
headers: { Authorization: `Bearer ${token}` }
});
Data Fetching (Client Component)
// Using fetch with auth
const [data, setData] = useState(null);
useEffect(() => {
const token = localStorage.getItem('auth_token');
fetch('/api/endpoint', {
headers: { Authorization: `Bearer ${token}` }
})
.then(res => res.json())
.then(setData);
}, []);
Error Handling
// API returns { error: "message" } or { data: ... }
const res = await fetch('/api/endpoint');
const json = await res.json();
if (!res.ok || json.error) {
// Handle error
console.error(json.error);
return;
}
// Use json.data
Ownership Checks (Backend)
// lib/auth.ts exports verifyToken(request)
const user = verifyToken(request);
if (!user) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
// Check ownership
const entity = await prisma.entity.findUnique({ where: { id } });
if (entity.userId !== user.id) {
return NextResponse.json({ error: 'Forbidden' }, { status: 403 });
}
Database Models (10)
| Model |
Key Relations |
Auth |
| User |
→ Artist (1), Label (1), Playlist (), Share () |
Base |
| Artist |
→ User (1), Label (1), Song (), Album () |
User role |
| Label |
→ User (1), Artist (), LabelInvitation () |
User role |
| Song |
→ Artist (1), Album (1), Genre (), Playlist () |
Public/Private |
| Album |
→ Artist (1), Song (*) |
Public |
| Playlist |
→ User (1), Song (*) |
Public/Private |
| Genre |
→ Song (*) |
Public |
| Share |
→ User (1) |
Token-based |
| LabelInvitation |
→ Label (1), Artist (1) |
Status-based |
| SongGenre |
→ Song (1), Genre (1) |
Join table |
Component Categories
| Category |
Components |
Count |
| Audio |
AudioPlayer, PlayerControls, WaveformDisplay |
3 |
| Cards |
SongCard, AlbumCard, ArtistCard, PlaylistCard, LabelCard, GenreBadge |
6 |
| Forms |
AuthForm, UploadForm, ProfileForm, CreatePlaylistModal |
4 |
| Navigation |
Header, NavLink, UserMenu, SearchBar |
4 |
| Sharing |
ShareButton, ShareModal |
2 |
| Display |
TrackList |
1 |
Workflow Commands
| Command |
Purpose |
/workflow:spawn |
Start automated workflow |
/workflow:status |
Check current state |
/workflow:approve |
Approve current gate |
/workflow:reject |
Reject with feedback |
/workflow:resume |
Resume interrupted workflow |
/guardrail:init |
Initialize manifest (manual) |
/guardrail:design |
Add entities (manual) |
/guardrail:implement |
Implement entities (manual) |
/eureka:index |
Generate documentation |
Project Structure
sonic-cloud/
├── app/ # Next.js App Router (pages + API)
│ ├── api/ # REST API endpoints (30 files)
│ └── [pages]/ # Frontend pages (13 pages)
├── components/ # React components (36 files)
├── lib/ # Utilities (auth, db, sharing)
├── types/ # TypeScript definitions (4 files)
├── prisma/ # Database schema
├── .workflow/ # Guardrail workflow state
├── .claude/ # Claude commands
└── skills/ # Custom skills (orchestrator, docs)
Statistics
- Total Files: 107 TypeScript files
- API Endpoints: 40 (REST)
- Database Models: 10 (Prisma)
- Pages: 13 (App Router)
- Components: 20 (reusable)
- LOC: ~15,000 lines
Generated by Eureka Documentation Pipeline | Sonic Cloud v0.1.0