Add Your Track (File Upload)
Name a track, pick a file, upload
Overview
The primary way to add a track: name it, pick a local audio file (WAV, MP3, AIFF, M4A, OGG, FLAC), upload. Works the same regardless of which storage backend the song uses — see Storage Backends for what actually happens on upload.
How it works
- A track name is required before the file input is enabled (
trackName.trim()) — this is what the uploaded filename gets slugified to, not the original filename. uploadTrackFile()insrc/lib/trackUpload.tsis the single shared upload path — it's also used by GarageBand import and mic recording, so all three entry points hit the same GitHub/Blob branching logic and never diverge.- On success,
onTracksChanged()triggers a re-fetch of the live track listing (no local caching — see the storage backends doc) and the form resets (track name cleared, file input cleared).
iPhone / Voice Memos note
iOS sandboxes Voice Memos recordings inside that app's own container — they are not visible to Safari's file picker until manually exported. A help note in the upload panel tells users to open the recording in Voice Memos, tap Share → Save to Files, then use "Choose file" here. The alternative is recording directly in the browser instead — see In-Browser Mic Recording, which was added specifically to route around this.
Key files
| File | Role |
|---|---|
src/components/MultiTrackPlayer.tsx | Upload panel UI (track name input, file picker) |
src/lib/trackUpload.ts | uploadTrackFile() — shared upload path, slugifyTrackName() |
Limitations / notes
- No drag-and-drop — file selection only.
- No upload progress bar beyond a short status string (
Authorizing…/Uploading…etc.) — no percentage/byte progress. - Only the song's owner can actually upload — enforced server-side (
onBeforeGenerateTokenin/api/blob/upload, and the GitHub token lookup being scoped to the requesting user). The upload panel itself isn't hidden or disabled for non-owner viewers, though, so a signed-in collaborator without upload rights sees the same "Choose file"/"Record" controls and only finds out via a failed request.