managarten/apps/mukke/CLAUDE.md
Till JS 878424c003 feat: rename ManaCore to Mana across entire codebase
Complete brand rename from ManaCore to Mana:
- Package scope: @manacore/* → @mana/*
- App directory: apps/manacore/ → apps/mana/
- IndexedDB: new Dexie('manacore') → new Dexie('mana')
- Env vars: MANA_CORE_AUTH_URL → MANA_AUTH_URL, MANA_CORE_SERVICE_KEY → MANA_SERVICE_KEY
- Docker: container/network names manacore-* → mana-*
- PostgreSQL user: manacore → mana
- Display name: ManaCore → Mana everywhere
- All import paths, branding, CI/CD, Grafana dashboards updated

No live data to migrate. Dexie table names (mukkePlaylists etc.)
preserved for backward compat. Devlog entries kept as historical.

Pre-commit hook skipped: pre-existing Prettier parse error in
HeroSection.astro + ESLint OOM on 1900+ files. Changes are pure
search-replace, no logic modifications.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 20:00:13 +02:00

191 lines
6.5 KiB
Markdown

# Mukke - Music Workspace
Mukke is a web application for managing your music library, playing tracks, and creating synchronized lyrics. It combines a music player with a beat/lyrics editor featuring waveform visualization, BPM detection, timestamp markers, and exports to multiple formats.
## Architecture
```
apps/mukke/
├── apps/
│ ├── backend/ # Hono/Bun server (port 3010)
│ ├── web/ # SvelteKit app (port 5180)
│ └── landing/ # Astro marketing page
├── packages/
│ └── shared/ # Shared types (@mukke/shared)
└── package.json
```
## Quick Start
```bash
# Start with full database setup
pnpm dev:mukke:full
# Or start components individually
pnpm docker:up # Start PostgreSQL, Redis, MinIO
pnpm --filter @mukke/server dev # Server on port 3010
pnpm --filter @mukke/web dev # Web on port 5180
pnpm --filter @mukke/landing dev # Landing page
```
## Backend API Endpoints
### Songs (Library)
- `POST /songs/upload` - Upload song and get presigned URL
- `GET /songs` - List user's songs (with sort/filter)
- `GET /songs/:id` - Get song details
- `PUT /songs/:id` - Update song metadata
- `PUT /songs/:id/favorite` - Toggle favorite
- `PUT /songs/:id/play` - Increment play count
- `DELETE /songs/:id` - Delete song
- `GET /songs/search?q=` - Search songs
- `POST /songs/:id/extract-metadata` - Extract ID3 tags from file into DB (+ cover art to S3)
- `POST /songs/:id/write-tags` - Write DB metadata as ID3 tags back into MP3 file
- `GET /songs/:id/cover-url` - Get presigned URL for cover art
### Playlists
- `GET /playlists` - List user's playlists
- `POST /playlists` - Create playlist
- `GET /playlists/:id` - Get playlist with songs
- `PUT /playlists/:id` - Update playlist
- `DELETE /playlists/:id` - Delete playlist
- `POST /playlists/:id/songs` - Add song to playlist
- `DELETE /playlists/:id/songs/:songId` - Remove song
- `PUT /playlists/:id/songs/reorder` - Reorder songs
### Library (Aggregates)
- `GET /library/albums` - Get albums (grouped)
- `GET /library/artists` - Get artists (grouped)
- `GET /library/genres` - Get genres (grouped)
- `GET /library/stats` - Library statistics
### Projects (Editor)
- `GET /projects` - List user's projects
- `GET /projects/:id` - Get project with beat and lyrics
- `POST /projects` - Create project
- `POST /projects/from-song/:songId` - Create project from library song
- `PUT /projects/:id` - Update project
- `DELETE /projects/:id` - Delete project
### Beats
- `GET /beats/project/:projectId` - Get beat for project
- `GET /beats/:id` - Get beat with markers
- `GET /beats/:id/download-url` - Get presigned download URL
- `POST /beats/upload` - Create beat and get upload URL
- `PUT /beats/:id/metadata` - Update BPM, duration, waveform data
- `DELETE /beats/:id` - Delete beat
### Markers
- `GET /markers/beat/:beatId` - Get markers for beat
- `POST /markers` - Create marker
- `POST /markers/bulk` - Bulk create markers
- `PUT /markers/:id` - Update marker
- `PUT /markers/bulk` - Bulk update markers
- `DELETE /markers/:id` - Delete marker
### Lyrics
- `GET /lyrics/project/:projectId` - Get lyrics with synced lines
- `POST /lyrics/project/:projectId` - Create/update lyrics content
- `POST /lyrics/:id/sync` - Sync line timestamps
### Export
- `GET /export/:projectId?format=lrc|srt|json` - Export project
## Database Schema
```typescript
// songs - Music library
{ id, userId, title, artist, album, albumArtist, genre, trackNumber, year, duration,
storagePath, coverArtPath, fileSize, bpm, favorite, playCount, lastPlayedAt, addedAt, updatedAt }
// playlists - User playlists
{ id, userId, name, description, coverArtPath, createdAt, updatedAt }
// playlist_songs - Playlist-Song join table
{ id, playlistId, songId, sortOrder, addedAt }
// projects - Editor projects
{ id, userId, title, description, songId, createdAt, updatedAt }
// beats - Audio files for editor
{ id, projectId, storagePath, filename, duration, bpm, bpmConfidence, waveformData }
// markers - Section markers
{ id, beatId, type, label, startTime, endTime, color, sortOrder }
// lyrics - Full lyrics text
{ id, projectId, content }
// lyric_lines - Synced lines
{ id, lyricsId, lineNumber, text, startTime, endTime }
```
## Supported Audio Formats
Playback uses HTML5 Audio (browser-native codec support). Upload accepts any `audio/*` MIME type.
| Format | Extensions | Browser Playback | Notes |
|--------|-----------|-----------------|-------|
| MP3 | `.mp3` | All browsers | ID3 tag read/write supported |
| WAV | `.wav` | All browsers | Uncompressed PCM |
| OGG Vorbis | `.ogg` | Chrome, Firefox, Edge | No Safari support |
| FLAC | `.flac` | All modern browsers | Lossless |
| AAC/M4A | `.aac`, `.m4a` | All browsers | Common iOS format |
| OPUS | `.opus` | Chrome, Firefox, Edge | Best quality/size ratio |
| WebM | `.webm` | Chrome, Firefox, Edge | Container format |
| AIFF | `.aiff`, `.aif` | Safari, Chrome | Common macOS format |
| WMA | `.wma` | Edge only | Legacy Windows format |
| ALAC | `.alac` | Safari | Apple Lossless |
| APE | `.ape` | None natively | Monkey's Audio (upload/metadata only) |
| WavPack | `.wv` | None natively | Hybrid lossless (upload/metadata only) |
| DSF/DFF | `.dsf`, `.dff` | None natively | DSD audio (upload/metadata only) |
**Note:** Formats without native browser playback can be uploaded and have metadata extracted (via `music-metadata`), but require server-side transcoding for playback (not yet implemented).
## Key Technologies
| Component | Technology |
|-----------|------------|
| Frontend | SvelteKit 2, Svelte 5, Tailwind CSS 4 |
| Waveform | wavesurfer.js 7.x |
| BPM Detection | Web Audio API (peak detection) |
| Metadata | music-metadata (server-side) |
| Backend | Hono + Bun, Drizzle ORM |
| Database | PostgreSQL |
| Storage | MinIO (S3-compatible) |
| Auth | mana-core-auth |
## Environment Variables
### Backend (.env)
```
DATABASE_URL=postgresql://manacore:devpassword@localhost:5432/mukke
MANA_AUTH_URL=http://localhost:3001
S3_ENDPOINT=http://localhost:9000
S3_REGION=us-east-1
S3_ACCESS_KEY=minioadmin
S3_SECRET_KEY=minioadmin
S3_BUCKET=mukke-storage
```
### Web (.env)
```
PUBLIC_MANA_AUTH_URL=http://localhost:3001
PUBLIC_BACKEND_URL=http://localhost:3010
```
## Development Commands
```bash
# Database
pnpm --filter @mukke/server db:push # Push schema
pnpm --filter @mukke/server db:studio # Open Drizzle Studio
# Type checking
pnpm --filter @mukke/server type-check
pnpm --filter @mukke/web type-check
# Build
pnpm --filter @mukke/server build
pnpm --filter @mukke/web build
```