Spotify Wrapped-style recap generator for ListenBrainz, Last.fm, and Navidrome. Built with Flask.
[!IMPORTANT] Rebranded to Make a Wrapped (was ListenBrainz Wrapped). Site's back up — if something's broken, open a GitHub issue.
New 2025 templates are out!

wrapped.devmatei.com - built by devmatei.com
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
copy .env.example to .env and fill in the basics:
FLASK_ENV=production
SECRET_KEY=<something>
LASTFM_API_KEY=<your-lastfm-key>
# set HTTP_PROXY / HTTPS_PROXY if you tunnel through a proxy
run it:
gunicorn -w 4 -b 0.0.0.0:8000 wrapped-fm:app
or locally:
./start.sh <host> <port>
or with Docker (change the port in the compose file first):
sudo docker compose up -d
LISTENBRAINZ_API=https://api.listenbrainz.org/1
MUSICBRAINZ_API, COVER_ART_API
LISTENBRAINZ_RANGE=this_year
AVERAGE_TRACK_LENGTH_MINUTES, COVER_ART_LOOKUP_LIMIT
LASTFM_API_KEY - required for Last.fm stats + better artist images
LASTFM_API, LASTFM_USER_AGENT
HTTP_TIMEOUT, HTTP_POOL_MAXSIZE, LISTENBRAINZ_CACHE_TTL, LISTENBRAINZ_CACHE_SIZE
APP_RATE_LIMIT, APP_STATS_RATE_LIMIT, APP_IMAGE_RATE_LIMIT, APP_MAX_TOP_RESULTS
APP_IMAGE_CONCURRENCY, APP_IMAGE_QUEUE_LIMIT, APP_IMAGE_QUEUE_TIMEOUT
TEMP_ARTWORK_TTL_SECONDS, TEMP_ARTWORK_MAX_BYTES
WRAPPED_COUNT_FILE (defaults to data/wrapped-count.txt)
WRAPPED_COUNT_SINCE - label for when you started counting wraps (ISO date string)
APP_RATE_LIMIT_SALT, APP_TRUST_PROXY_HEADERS
I self-host my music library on Navidrome and don't use Spotify, but all my friends post their Wrapped every year and everyone's like "wait what's that?" when you show them a ListenBrainz stats page. so I built this. same vibe, works with open music platforms.
go flex your scrobbles at wrapped.devmatei.com :)
I'm Matei (DevMatei) - full-stack dev from Moldova. I build random web tools, run a homelab full of self-hosted stuff, and care way too much about my music library. Check out my other projects at devmatei.com or hit me up on socials if you wanna talk projects or self-hosting.
See CONTRIBUTING.yml for setup, style notes, and the PR checklist. TL;DR: keep PRs focused, run python -m py_compile wrapped-fm.py, and attach screenshots for any UI changes.
originally made for Last.fm only by jeff parla <3
AGPL-3.0 - share alike
not affiliated with Spotify, ListenBrainz, Last.fm, Navidrome, or MusicBrainz. just a fan thing built for fun.
$ claude mcp add make-a-wrapped \
-- python -m otcore.mcp_server <graph>