corpus: self-hosted listenbrainz and last.fm frontend

Lobsters Hottest Tools

Summary

Corpus is a self-hosted frontend for ListenBrainz and Last.fm that stores music scrobbles, metadata, and cover images with an interactive PureScript-based interface for exploring listening habits.

<p>Works as a self-hosted proxy that fetches listening history from either Last.fm or MusicBrainz, adds metadata from MusicBrainz (falling back to Last.fm and Discogs) and caches cover images to an S3 bucket. Everything is stored in DuckDB (each user has their own database) and it's been humming along quite well even for larger profiles (200k scrobbles).</p> <p>I always worry that these services can disappear without a warning and with them also amazingly extensive listening histories.</p> <p>I used LLMs quite a lot as I was learning about Purescript and Elm on the fly on the weekends and this is one of the projects I have been thinking about for a long time since other alternatives just seemed a bit lackluster.</p> <p><a href="https://lobste.rs/s/qxhzxh/corpus_self_hosted_listenbrainz_last_fm">Comments</a></p>
Original Article
View Cached Full Text

Cached at: 04/20/26, 02:44 PM

mtmn/corpus

Source: https://github.com/mtmn/corpus

corpus

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.

You can see it for yourself - scrobbler.mtmn.name

Documentation

  • Architecture — Deep dive into the system components, data flow, and FFI usage.
  • DuckDB — Schema details, analytical queries, and tools for data exploration.

Usage

This project uses just and Nix for development and deployment.

Development

# Enter the development shell (includes PureScript, DuckDB, etc.)
just shell

# Build
just nix build

# Run the binary built by Nix
just nix run

Build

# 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 run

Environment variables

VariableDefaultDescription
CORPUS_USERS_FILEusers.jsonPath to the multi-user config file
DATABASE_PATH(cwd)Root directory for all user database files
PORT8000HTTP port to listen on
LASTFM_API_KEYLast.fm API key (required when any user has lastfmUser set; also used for genre and cover art fallback)
DISCOGS_TOKENDiscogs token for cover art and genre fallback
S3_BUCKETS3 bucket name for cover art caching and backups
S3_REGIONus-east-1S3 region
AWS_ACCESS_KEY_IDS3 credentials
AWS_SECRET_ACCESS_KEYS3 credentials
AWS_ENDPOINT_URLS3-compatible endpoint (e.g. for MinIO)
AWS_S3_ADDRESSING_STYLESet to path for path-style S3 URLs
COSINE_API_KEYcosine.club API key for similar tracks
METRICS_ENABLEDfalseSet to true to expose Prometheus metrics at /metrics

Per-user configuration

FieldDefaultDescription
slugURL slug ("" for root user, "filip" for /u/filip)
nameDisplay name for the user (defaults to slug if not provided)
listenbrainzUserListenBrainz username to sync scrobbles from
lastfmUserLast.fm username to sync scrobbles from
databaseFilecorpus.dbPath to the user’s DuckDB database file
initialSyncfalsePerform a full historical sync on first run
coverCacheEnabledtrueEnable cover art caching to S3
backupEnabledfalseEnable database backups to S3
backupIntervalHours24Backup frequency in hours

Similar Articles

Record Club is trying to be Letterboxd for music nerds

The Verge

Record Club is a new social platform for music lovers to rate, review, and catalog albums, inspired by Letterboxd, with features like custom lists, artist and label following, and integration with MusicBrainz.