Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/cocreating/4StemPlayer/llms.txt

Use this file to discover all available pages before exploring further.

Adding a song to 4Stem Band Player is a fully offline, script-driven process. There is no upload UI — you place files in the right folder, run a couple of npm scripts, and the song becomes part of the static catalog. This guide walks through every step from folder creation to the final release check you should run before committing or deploying.

The Ingestion Steps

1
Create the song folder
2
Create a new subfolder under static/songs/ using a stable, URL-safe name with no spaces. The folder name becomes the song’s unique ID in the manifest and in all stem URLs.
3
mkdir static/songs/MyNewSong
4
Good folder names:
5
MyNewSong
BlueMonday
GloryBox
6
Avoid spaces. My New Song would require URL encoding everywhere it appears and is not supported as a folder name. If your song title contains spaces, use a CamelCase or concatenated slug for the folder and set the title field in song.json to the full display name.
7
Add song.json
8
Create static/songs/<Folder>/song.json with at minimum the five required fields:
9
{
  "title": "My New Song",
  "artist": "My Band",
  "key": "A minor",
  "bpm": 120,
  "timeSignature": "4/4"
}
10
Add optional fields as needed. A fully specified example with chords, sections, and duration metadata:
11
{
  "title": "My New Song",
  "artist": "My Band",
  "key": "A minor",
  "bpm": 120,
  "timeSignature": "4/4",
  "duration": "4:32",
  "durationSeconds": 272,
  "chords": {
    "intro": {
      "progression": "Am | F | C | G"
    },
    "verse": {
      "label": "Verse",
      "progression": "Am | F | C | G",
      "notes": "Repeat twice before chorus."
    },
    "chorus": {
      "progression": "F | G | Am | Am"
    }
  },
  "notes": "Rehearsal notes visible in the metadata panel.",
  "sections": [
    { "label": "Intro",  "start": 0 },
    { "label": "Verse",  "start": 8 },
    { "label": "Chorus", "start": 32 }
  ]
}
12
See the song.json reference for the full schema and validation rules.
13
Add lyrics.md
14
Create static/songs/<Folder>/lyrics.md. The file must exist — validation will report an error if it is missing. An empty file is accepted with a warning, so you can create a placeholder now and fill it in later:
15
touch static/songs/MyNewSong/lyrics.md
16
A populated example:
17
# My New Song

[Verse]
First lyric line here.
Second lyric line here.

[Chorus]
Chorus lyric line.
18
Add the MP3 stem files
19
Place the required stem files in the song folder. The three required stems are bass, drums, and vocals. Optional stems (guitar, strings, fx, other) are loaded dynamically if their files are present.
20
Recommended naming convention — use the folder name as the prefix:
21
static/songs/MyNewSong/MyNewSong_bass.mp3
static/songs/MyNewSong/MyNewSong_drums.mp3
static/songs/MyNewSong/MyNewSong_vocals.mp3
static/songs/MyNewSong/MyNewSong_guitar.mp3   ← optional
22
Stem filename resolution — the scripts resolve each stem file by checking, in order:
23
  • <Folder>_<stem>.mp3 (e.g. MyNewSong_bass.mp3)
  • <SongTitle>_<stem>.mp3 (e.g. My New Song_bass.mp3)
  • Any file in the folder whose lowercase name ends with _<stem>.mp3
  • 24
    All required files must be present and non-empty. Any optional file found in the folder must also be non-empty.
    25
    Run npm run songs:prepare
    26
    Once the folder is populated, run the preparation script to validate, generate waveform peaks, and rebuild the manifest:
    27
    npm run songs:prepare
    
    28
    This command performs four steps in sequence:
    29
  • Detect BPM — reads the drums stem and writes the detected BPM back into song.json (skip with --skip-bpm-detect to preserve a manually curated value).
  • Validate — checks every song folder for required files and valid metadata.
  • Generate peaks — creates .peaks.json waveform data files for any stem that doesn’t have one yet, or whose MP3 has changed since the peak file was last written.
  • Regenerate manifest — rewrites static/songs/manifest.json to include the new song.
  • 30
    If validation fails, the output will list each error. Fix the reported issue and run the command again.
    31
    songs:prepare calls songs:peaks internally, which requires ffmpeg on your PATH. If ffmpeg is not installed, peak generation will fail with Peak generation requires ffmpeg to be available on PATH. Install ffmpeg and rerun, or pass --skip-peaks to skip peak generation for now.
    32
    If you only need to refresh peak files or regenerate the manifest without letting the script rewrite your carefully tuned BPM value, pass --skip-bpm-detect:
    npm run songs:prepare -- --skip-bpm-detect
    
    33
    Run npm run songs:release before committing
    34
    Before committing, pushing, or deploying any song changes, run the full release workflow:
    35
    npm run songs:release
    
    36
    This extends songs:prepare with additional quality gates:
    37
  • Detect BPM → validate → generate peaks → regenerate manifest
  • npm run check — TypeScript and Svelte diagnostics
  • npm test — unit test suite
  • npm run build — full static production build
  • 38
    If any step fails, fix the issue and run songs:release again. Only commit when the command exits cleanly.

    Removing an Optional Stem

    To remove an optional stem (for example, guitar) from an existing song:
    1. Delete the stem MP3: static/songs/<Folder>/<Folder>_guitar.mp3
    2. Delete its peak file: static/songs/<Folder>/<Folder>_guitar.peaks.json
    3. Regenerate the catalog:
      npm run songs:prepare
      npm run build
      
    The manifest will no longer include the stem, and the mixer will render without it on the next page load.

    Troubleshooting

    The folder does not contain one of the required stem files (bass, drums, or vocals). Check that the file exists and that its name ends with _bass.mp3, _drums.mp3, or _vocals.mp3. The resolution order is <Folder>_<stem>.mp3<SongTitle>_<stem>.mp3 → any file ending in _<stem>.mp3. Rename the file to match one of those patterns and rerun songs:prepare.
    A required field (title, artist, key, bpm, or timeSignature) is absent or empty in song.json. Open the file and add the missing field, then rerun songs:prepare.
    The bpm field is present but written as a JSON string. Change it from "120" to the bare number 120:
    { "bpm": 120 }
    
    The songs:peaks script calls ffmpeg as an external process and it was not found. Install ffmpeg for your platform (e.g. brew install ffmpeg on macOS, or download from ffmpeg.org), ensure it is on your PATH, and rerun npm run songs:prepare.
    By default, songs:peaks skips a stem’s peak file if it is newer than the MP3. If you replaced an MP3 but the peak file timestamp wasn’t reset, pass --force-peaks to regenerate all peaks unconditionally:
    npm run songs:prepare -- --force-peaks
    

    Build docs developers (and LLMs) love