Complete multiroom audio + navigation dashboard: - Docker stack: SignalK, Snapcast (4 zones), librespot, shairport-sync, Mopidy, Jellyfin, Portainer - React 18 + Vite dashboard with nautical dark theme - Full mock system (SignalK NMEA simulation, Snapcast zones, Mopidy player) - Real API clients for all services with reconnect logic - SVG instruments: Compass, WindRose, Gauge, DepthSounder, SpeedLog - Pages: Overview, Navigation, Audio (zones/radio/library), Systems - Dev mode runs fully without hardware (make dev) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Bordanlage – Boat Onboard System
A complete multiroom audio + navigation dashboard system for boats. Runs on any Docker-capable computer – fully simulated in dev mode (no hardware needed).
Prerequisites
- Docker Desktop (or Docker Engine + Compose)
make- For Spotify Connect: a Spotify Premium account
Quick Start
cd bordanlage
make dev
Dashboard: http://localhost:8080
Service URLs
| Service | URL | Description |
|---|---|---|
| Dashboard | http://localhost:8080 | Main touch UI |
| SignalK | http://localhost:3000 | Navigation data + chart viewer |
| Mopidy/Iris | http://localhost:6680/iris/ | Music player UI |
| Snapcast Web | http://localhost:1780 | Multiroom audio control |
| Jellyfin | http://localhost:8096 | Media library |
| Portainer | http://localhost:9000 | Docker management |
Spotify Connect
- Run
make dev(ormake booton the boat) - Open Spotify on your phone/computer
- Tap the device icon (bottom right) → look for "Bordanlage"
- If it doesn't appear automatically: Go to Connect to a Device → enter the IP of the host machine manually
On Linux (boat): set
network_mode: hostfor thelibrespotservice indocker-compose.ymlfor reliable mDNS discovery.
AirPlay
- Ensure the
shairportcontainer is running - On your iPhone/Mac: open Control Center → tap AirPlay → select "Bordanlage AirPlay"
On Mac: AirPlay works natively via Bonjour. On Windows WSL2: the
avahicontainer indocker-compose.dev.ymlhandles mDNS.
Adding Music
Drop audio files into ./music/. Mopidy and Jellyfin both mount this directory.
Trigger a Mopidy library scan:
curl -s http://localhost:6680/mopidy/rpc -d '{"jsonrpc":"2.0","id":1,"method":"local.scan"}' \
-H "Content-Type: application/json"
For Jellyfin: open http://localhost:8096 → Settings → Libraries → Scan.
Connecting Real NMEA Hardware
Edit docker-compose.yml and uncomment the signalk device section:
signalk:
devices:
- /dev/ttyUSB0:/dev/ttyUSB0 # NMEA 0183 via USB-Serial
Then configure the NMEA connection in SignalK at http://localhost:3000 → Server → Connections.
For NMEA 2000: use a Yacht Devices YDNU-02 or similar USB gateway.
Migration to Real Boat
Changes needed in docker-compose.yml:
- Audio output per zone: add
--soundcard hw:N,0to eachzone-*command and uncomment/dev/snd - Spotify/AirPlay discovery: set
network_mode: hostforlibrespotandshairport - Hardware video decoding (optional): uncomment
/dev/driinjellyfin - NMEA hardware: uncomment
/dev/ttyUSB0insignalk - Set
DEV=falsein.env
Run make boot instead of make dev.
Troubleshooting
Spotify device not showing up on Mac:
- Ensure port 57621 (UDP+TCP) is accessible. Docker Desktop on Mac sometimes blocks UDP.
- Try connecting manually: Spotify → "Connect to a Device" → "Connect to [IP]"
AirPlay not visible on Windows:
- The
avahicontainer requires D-Bus. Run Docker Desktop with host networking or use WSL2.
Snapcast zones show as offline:
- Audio pipes must exist before snapserver starts. Run
make pipesorbash scripts/init-pipes.sh
Mopidy won't start:
- Check
docker compose logs mopidy. The custom Dockerfile installs plugins on first build; rebuild withmake rebuild
Dashboard shows "No signal":
- In dev mode this is normal until mock data initializes (1–2 seconds)
- In production: check that SignalK is running and the WebSocket URL is correct in
.env
Port conflicts:
- Edit the port mappings in
docker-compose.ymlordocker-compose.dev.yml