Mood radio you host yourself.
Drop in your mp3s, tag them by mood, hit play. Continuous shuffled playback per mood. No accounts, no tracking, no frameworks.
Stack: Go + SQLite + vanilla JS
# 1. Initialize the database
make db-init
# 2. Import your music (interactive — pick mood per batch)
make import-batch ARGS="/path/to/your/music"
# 3. Run
make run
# → http://localhost:8080git clone https://github.com/1mb-dev/driftfm.git
cd driftfm
make db-initPrerequisites: Go 1.25+, SQLite3 CLI, ffmpeg/ffprobe (for audio import and normalization).
Option A — Batch import (recommended):
# Import a directory of MP3s — prompts for mood selection
make import-batch ARGS="/path/to/focus-tracks"Option B — Single track with metadata:
make import FILE=song.mp3 MOOD=focusThe import script (scripts/import-track.sh) supports additional flags:
# Full metadata example
./scripts/import-track.sh song.mp3 \
--mood calm \
--title "Ocean Waves" \
--artist "Your Name" \
--energy low \
--bpm 72 \
--intensity 8 \
--time eveningRun ./scripts/import-track.sh --help for all options.
Normalize loudness across your library for consistent playback:
# Single file
make normalize FILE=audio/tracks/a/ocean-waves-001a.mp3
# Batch (all files in a directory)
./scripts/normalize-batch.sh audio/tracks/make run
# → http://localhost:8080Or build a binary:
make build
./bin/serverAfter adding new tracks or modifying the schema:
# Run pending migrations
make db-migrate
# Re-initialize from scratch (destructive)
make db-init| Mood | Vibe | Example Use |
|---|---|---|
| focus | Instrumental, ambient, post-rock | Deep work, coding |
| calm | Soft, gentle, meditative | Winding down, reading |
| energize | Upbeat, driving, anthemic | Morning, exercise |
| late_night | Chillwave, lo-fi, nocturnal | Late sessions, unwinding |
Development:
make build Build the server binary
make run Run the server (localhost:8080)
make dev Run with hot reload (requires air)
make test Run all tests
make clean Remove build artifacts
Code Quality:
make check Full quality gate (fmt, vet, lint, test)
make fmt Format code
make vet Run go vet
make lint Run linter (requires golangci-lint)
Setup & Database:
make setup Create data/ and audio/ directories
make db-init Initialize SQLite database
make db-migrate Run pending migrations
Audio:
make import FILE=<path> MOOD=<mood> Import single track
make import-batch ARGS=<dir> Import directory of tracks
make normalize FILE=<path> Normalize audio file
Environment variables override config.yaml values (see .env.example):
| Variable | Default | Description |
|---|---|---|
PORT |
8080 |
Server port |
DB_PATH |
data/inventory.db |
SQLite database path |
AUDIO_STORE_LOCAL_PATH |
audio |
Local audio directory |
# Build for Linux
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o bin/server ./cmd/server
# Copy to your server:
scp -r bin/server web/ config.yaml scripts/ user@host:/opt/driftfm/
# On the server:
mkdir -p /opt/driftfm/data /opt/driftfm/audio/tracks
sqlite3 /opt/driftfm/data/inventory.db < /opt/driftfm/scripts/migrations/schema.sql
PORT=8080 /opt/driftfm/serverFor production, put a reverse proxy (Caddy, nginx) in front for TLS and set up a systemd unit for process management.
| Endpoint | Description |
|---|---|
GET /api/moods |
List moods with track counts |
GET /api/moods/:mood/playlist |
Shuffled playlist for mood |
POST /api/tracks/:id/play |
Record listen event |
GET /health |
Health check |
GET /ready |
Readiness probe |
Browser ←→ Go server ←→ SQLite
↓
audio/tracks/
- Backend: Single Go binary, net/http, no framework
- Database: SQLite with WAL mode (pure Go driver, no CGO)
- Frontend: Vanilla JS, CSS variables, Web Audio API
- Audio: Local filesystem (
audio/tracks/)
MIT — see LICENSE.