1
0
Fork
You've already forked lytter
0
Lastfm statistics
  • Python 39%
  • JavaScript 37.4%
  • HTML 21.4%
  • CSS 1.9%
  • Pkl 0.3%
engeir 6a4a725303
Some checks failed
Release PR with CalVer / release-pr (push) Has been cancelled
Release PR with CalVer / create-release (push) Has been cancelled
fix(plot): some alignment issues..
Signed-off-by: engeir <38856990+engeir@users.noreply.github.com>
2026年05月31日 13:15:36 +02:00
.github ci(pinact): allow pinact to update workflow deps 2026年05月24日 12:15:55 +02:00
deployment refactor!: move from reflex to fastapi version ( #22 ) 2025年11月07日 20:56:40 +01:00
docs/superpowers fix(names): better normalization of artist/song names 2026年05月31日 11:10:15 +02:00
images feat(reflex): first successful "now playing" button 2023年12月22日 20:43:43 +01:00
leaflet style(fix): run the formatter 2026年04月02日 14:42:22 +02:00
src/lytter fix(plot): some alignment issues.. 2026年05月31日 13:15:36 +02:00
tests fix(names): better normalization of artist/song names 2026年05月31日 11:10:15 +02:00
.djlintrc refactor: migrate yearly stats to HTMX with djlint formatting 2025年11月12日 21:40:42 +01:00
.dockerignore refactor!: move from reflex to fastapi version ( #22 ) 2025年11月07日 20:56:40 +01:00
.editorconfig chore: initial commit 2023年06月05日 22:21:53 +02:00
.env.example feat(duration): add update command 2026年03月30日 23:35:28 +02:00
.flake8 chore: initial commit 2023年06月05日 22:21:53 +02:00
.gitignore refactor!: move from reflex to fastapi version ( #22 ) 2025年11月07日 20:56:40 +01:00
.mise.development.toml chore: update dev files 2026年03月21日 22:38:07 +01:00
.mise.toml chore(deps): add uv as project dependency 2026年05月14日 21:26:23 +02:00
.prettierrc.toml style(fix): run the formatter 2026年04月02日 14:42:22 +02:00
.python-version style(hk): use hk to format files 2025年11月09日 13:06:45 +01:00
.taplo.toml style(hk): relax the entry alignment 2025年11月09日 14:17:03 +01:00
CHANGELOG.md chore(release): 2026年5月9日 ( #71 ) 2026年05月31日 12:36:06 +02:00
CLAUDE.md feat(yearly): replace spaghetti ranking chart with enhanced bump chart 2026年05月16日 14:14:03 +02:00
cliff.toml style(fix): run the formatter 2026年04月02日 14:42:22 +02:00
compose.yml fix(docs): correctly handle permissions of the database 2025年11月20日 21:52:12 +01:00
Dockerfile.fastapi build(docker): follow more best practices 2025年11月12日 23:40:58 +01:00
fnox.toml chore(deps): add uv as project dependency 2026年05月14日 21:26:23 +02:00
hk.pkl chore(format): differentiate between check and write 2026年03月22日 10:03:32 +01:00
pitchfork.toml chore: update dev files 2026年03月21日 22:38:07 +01:00
pyproject.toml chore(release): 2026年5月9日 ( #71 ) 2026年05月31日 12:36:06 +02:00
README.md chore(release): 2026年5月9日 ( #71 ) 2026年05月31日 12:36:06 +02:00
uv.lock feat(alltime): make plots better for narrow screens 2026年05月31日 12:32:51 +02:00

lytter

Last.fm statistics dashboard built with FastAPI. Tracks scrobbles, displays listening history, and generates music stats with Plotly visualizations.

Configuration

Create .env with:

API_KEY=your_lastfm_api_key
API_SECRET=your_lastfm_api_secret
USER_NAME=your_lastfm_username
PASSWORD=your_lastfm_password
GENIUS_TOKEN=your_genius_api_token # optional, for lyrics
SPOTIFY_CLIENT_ID=your_spotify_client_id # optional, improves duration accuracy
SPOTIFY_CLIENT_SECRET=your_spotify_client_secret

Install

Run with Docker

First time setup:

# Create database file with correct permissions (important!)
touch music.db
sudo chown 1000:1000 music.db

Then run the container:

# Pull and run latest
docker pull ghcr.io/engeir/lytter:latest
docker run -d \
 --name lytter \
 --restart unless-stopped \
 -p 8000:8000 \
 -v ./music.db:/app/music.db \
 --env-file .env \
 ghcr.io/engeir/lytter:latest
# Or specific version
docker pull ghcr.io/engeir/lytter:2026年5月9日

Or use docker compose:

mise run du # or: docker compose up -d

Database Updates

Set up a cron job to update scrobbles automatically:

# Add to crontab (every 15 minutes)
*/15 * * * * docker exec lytter uv run lytter-cron >> ~/lytter-cron.log 2>&1

Manual update:

docker exec lytter uv run lytter-update

Local Development

Quick Start

# Install dependencies
mise run i # or: uv sync
# Set up environment variables
fnox export -f env -o .env
# Run dev server
mise run r # or: uv run lytter
# Access at http://localhost:8000
# Code quality
hk fix

Build & Push to Registry

Deploying new versions with

# Build, tag, and push (all-in-one)
mise run dbp
# Or step by step:
mise run db # Build: docker compose build
mise run dt # Tag for registry
mise run dp # Push to registry

To push to the GitHub container registry, create a PAT with read, write, delete package rights, then export the token and login, as described here.

Database Updates

The app fetches scrobbles incrementally (only new ones since last update).

# Manual update
uv run lytter-update
# Background updater (runs continuously)
uv run lytter-background
# Cron updater
uv run lytter-cron
# Check status
uv run lytter-status
# Check for gaps
uv run lytter-gaps
# Fetch durations for all tracks missing them
uv run lytter-duration
# Also retry previously failed lookups
uv run lytter-duration --retry-failed
# Re-fetch durations for the entire library (e.g. after adding a new source)
uv run lytter-duration --force

Or as modules:

uv run python -m lytter.update_db
uv run python -m lytter.cron_updater

Architecture

  • Framework: FastAPI with Jinja2 templates + HTMX
  • Database: SQLite (music.db)
  • APIs: Last.fm API (via pylast), Genius API (lyrics)
  • Visualizations: Plotly charts
  • Styling: Centralized CSS with variables (GitHub Dark theme)
  • Deployment: Single Docker container
  • Structure: Modern src/ layout with reusable macros

Features

  • Dashboard: Now playing, listening timeline, recent favorites, top artists
  • Artist Pages: Listening history charts, top songs/albums
  • Album/Song Pages: Detailed stats with breadcrumb navigation
  • Yearly Stats: Time patterns (24h/weekly), top 20 lists, monthly ranking evolution
  • Search: Fuzzy artist search with Unicode normalization
  • HTMX: Server-side rendering for dynamic content (minimal JavaScript)

References