A self-hosted ListenBrainz and Last.fm frontend that stores metadata and cover images.
It includes storing scrobbles, metadata enrichment, and an interactive PureScript frontend for exploration of your listening habits.
- Architecture — Deep dive into the system components, data flow, and FFI usage.
- DuckDB — Schema details, analytical queries, and tools for data exploration.
This project uses just and Nix for development and deployment.
# Enter the development shell
just shell
# Build
just nix build
# Run the binary built by Nix
just nix run# Install dependencies
npm install
npx spago install
# Build the project
npm run build
# Run tests
npx spago test
# Build an optimized release
npm run release
# Run the application
npx spago runCorpus provides a ListenBrainz-compatible endpoint for submitting scrobbles directly. This allows you to use any scrobbler that supports custom ListenBrainz endpoints.
POST /1/submit-listens
The API uses token-based authentication. A unique API token is automatically generated for each user when they first start the application. You can find your token in the server logs on startup:
[INFO] User 'mtmn' token: 550e8400-e29b-41d4-a716-446655440000
Include the token in the Authorization header of your requests:
Authorization: Token <your-token>
The endpoint accepts standard ListenBrainz JSON payloads. See the ListenBrainz API documentation for details.
| Variable | Default | Description |
|---|---|---|
CORPUS_USERS_FILE |
users.json |
Path to the multi-user config file |
DATABASE_PATH |
(cwd) | Root directory for all user database files |
PORT |
8000 |
HTTP port to listen on |
LASTFM_API_KEY |
— | Last.fm API key (required when any user has lastfmUser set; also used for genre and cover art fallback) |
DISCOGS_TOKEN |
— | Discogs token for cover art and genre fallback |
S3_BUCKET |
— | S3 bucket name for cover art caching and backups |
S3_REGION |
us-east-1 |
S3 region |
AWS_ACCESS_KEY_ID |
— | S3 credentials |
AWS_SECRET_ACCESS_KEY |
— | S3 credentials |
AWS_ENDPOINT_URL |
— | S3-compatible endpoint (e.g. for MinIO) |
AWS_S3_ADDRESSING_STYLE |
— | Set to path for path-style S3 URLs |
COSINE_API_KEY |
— | cosine.club API key for similar tracks |
METRICS_ENABLED |
false |
Set to true to expose Prometheus metrics at /metrics |
CORS_ORIGIN |
* |
Value for the Access-Control-Allow-Origin header on /proxy responses (e.g. https://mtmn.name) |
| Field | Default | Description |
|---|---|---|
slug |
— | URL slug ("" for root user, "filip" for /u/filip) |
name |
— | Display name for the user (defaults to slug if not provided) |
listenbrainzUser |
— | ListenBrainz username to sync scrobbles from |
lastfmUser |
— | Last.fm username to sync scrobbles from |
databaseFile |
corpus.db |
Path to the user's DuckDB database file |
coverCacheEnabled |
true |
Enable cover art caching to S3 |
backupEnabled |
false |
Enable database backups to S3 |
backupIntervalHours |
24 |
Backup frequency in hours |