Two issues over one bar, because they are one relayout. #42's own findings say so: giving wa-slider a label grows it 6px to 14px and moves the transport, which is #23's subject, so doing them in sequence means measuring the bar twice and throwing the first set away. The bar was `320px 1fr auto`, so the transport sat in the middle of what the metadata and the queue button did not use — its centre was ~140px right of the window's at every width. The outer two tracks are the same expression now, so the middle is centred by construction. The side width is the metadata's, capped at a quarter of the bar, and the cap was measured as a regression before it was a decision: reserving the full `--now-playing-width` on both sides is perfectly centred and takes the seek bar's track from 257px to 61px at 800px, and to 0 at 200% text. The control you drag was paying for the symmetry. With the cap it is 246, which is parity. It is a `min()` rather than a breakpoint because that variable is user state — the metadata has a drag handle — and tying both sides to it is also what keeps dragging meaningful; a plain `1fr … 1fr` centres just as well and silently makes the handle a no-op. The volume moved out of `audio-player` into the bar because the transport column has to hold the transport and nothing else, and it joins the queue button in one cell rather than a second column, since the centring compares columns. It is a slider by default and a popup by setting. The stored flag names the *popup*, which is this config's polarity rule — the zero value has to be the intended answer, so an existing config.toml gets the new default with no migration. Inline, the icon is the mute toggle and is named after that action rather than the state, because with the slider beside it there is nothing to disclose; the component tier now covers both presentations rather than whichever is default. Three nested rules in this block began with a bare element selector, which Chrome 120 relaxed and the phone's Chrome 113 **silently drops** — including the ellipsis on the bar's own title and artist, which has therefore never truncated on the device. They are `&`-prefixed now. Filed as #154 for the class and for a check. `bottom-bar.spec.ts` pins both halves separately on purpose: an uncapped build is perfectly centred and fails only the seek-bar width, so a spec asserting centring alone would have passed the regression above. Both were verified by mutation. Closes #23 Closes #42
YellowJacket
Music how it was meant to bee.
YellowJacket is a fast, cross-platform desktop music player for your local collection. It plays your files, keeps your library tidy, and helps you discover and organize your music — all in a clean, responsive interface. No accounts, no streaming, no telemetry: just your music on your machine.
Runs on Linux, macOS, and Windows.
Features
Play your music
- Plays MP3, FLAC, OGG Vorbis, and WAV
- Play, pause, seek, and volume control with a mute toggle
- Gapless, glitch-free seeking backed by a read-ahead buffer
- A queue you can add to, reorder, and shuffle, with play-next support
- Shuffle and repeat (off / all / one)
- Picks up right where you left off — remembers your track, position, and volume between sessions
- Media-key and MPRIS support on Linux, so your desktop's playback controls just work
Keep your library organized
- Point it at your music folders and it scans them automatically
- Reads tags and embedded cover art, and de-duplicates artwork so it isn't stored twice
- Incremental sync — only new or changed files get reprocessed, and deleted files are cleaned up
- Browse by album, artist, or genre, or search across everything
- Mark favorites and see what you've been listening to with play history
- Edit track tags directly when something's off
Playlists
- Create playlists, drag tracks in, and reorder them
- Smart playlists that build themselves from rules (by genre, rating, play count, and more)
- Pin a default playlist and spot duplicate tracks at a glance
Discover and clean up (powered by MusicBrainz)
- Explore — browse artists, releases, and genres from the MusicBrainz catalog, not just what's already in your library
- Auto-tag — match your files against MusicBrainz to fill in correct artist, album, and track metadata, with a review step before anything is written
- Lyrics search — find a track by a line you remember
Install
Download the latest build for your platform from the releases page.
| Platform | Download |
|---|---|
| Linux | yellowjacket-linux-amd64 |
| macOS | yellowjacket-darwin-universal.app.zip (Apple Silicon + Intel) |
| Windows | yellowjacket-windows-amd64.exe |
Prefer to build it yourself? See Building from source.
Getting started
- Launch YellowJacket.
- Open Settings and add the folder(s) where your music lives.
- Let the initial scan finish — you'll see progress as it works.
- Browse by album, artist, or genre, queue something up, and press play.
Your library and settings are stored locally:
| Linux / macOS | Windows | |
|---|---|---|
| Config | ~/.config/yellowjacket/ |
%LOCALAPPDATA%\yellowjacket\config |
| Library data | ~/.local/share/yellowjacket/ |
%LOCALAPPDATA%\yellowjacket\data |
Building from source
YellowJacket is built with Go and a Lit/TypeScript frontend, bridged by the Wails framework.
Prerequisites
| Tool | Version |
|---|---|
| Go | 1.25+ |
| Node.js | 22+ |
| pnpm | 10+ |
| Wails CLI | v3 — vendored, no install needed (go tool wails3) |
The Wails v3 CLI resolves from the tool block in go.mod, so there is nothing
to install globally; make setup fetches it with the rest of the tooling.
On Linux, install the system libraries Wails needs. v3 builds against GTK4 + WebKitGTK 6.0 by default:
sudo apt-get install libasound2-dev libgtk-4-dev libwebkitgtk-6.0-dev # Debian/Ubuntu
sudo pacman -S alsa-lib gtk4 webkitgtk-6.0 # Arch
A machine without webkitgtk-6.0 can still build with -tags gtk3 against the
older WebKit2GTK 4.1 stack, but that is an escape hatch, not what CI or a
release builds.
macOS and Windows need no extra system packages. Run go tool wails3 doctor to
check your environment.
Build
make setup # install tooling and git hooks
make dev # run with hot-reload
make build-prod # produce a release binary
More detail for contributors lives in CLAUDE.md — the
architecture, the conventions and the reasons behind them. What is
being worked on is the issue
tracker; #73 is the
roadmap.