# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview Diora is a Django-based internet radio player with user accounts, track history, Last.fm scrobbling, and PWA support. No build tools or bundlers — pure Django with vanilla JavaScript. ## Development Commands ```bash # Setup pip install -r requirements.txt cp .env.example .env # then edit with your values python manage.py migrate python manage.py createsuperuser # Run python manage.py runserver # Database python manage.py makemigrations python manage.py migrate ``` There is no test suite configured. Django's built-in test runner would be used if tests are added: `python manage.py test`. ## Environment Variables (`.env`) ``` SECRET_KEY=change-me DEBUG=True AMAZON_AFFILIATE_TAG=diora-20 LASTFM_API_KEY= LASTFM_API_SECRET= ``` ## Architecture Two Django apps: **`radio/`** — Core player functionality - `models.py`: `SavedStation`, `StationPlay`, `TrackHistory`, `FocusSession` - `icy.py`: Parses ICY metadata from streaming HTTP responses (extracts track titles from radio streams) - `lastfm.py`: Last.fm API wrapper (scrobbling, track love/unlove) - `views.py`: Player page, SSE endpoint for real-time metadata, track recording, station CRUD **`accounts/`** — Authentication and user profiles - `models.py`: `UserProfile` (extends Django's `User` via signal; stores Last.fm session key, background image, scrobble preference) - `views.py`: Registration, login, Last.fm OAuth flow, background image upload **Frontend (`static/js/`)** - `app.js`: All client-side logic — HTML5 Audio playback, SSE connection for live metadata, station management UI, focus timer - `sw.js`: Service worker for PWA installability - No build step — files are served directly **Templates (`templates/`)** - `base.html`: Main layout with navbar - `radio/player.html`: Single-page player UI - `accounts/`: Auth and settings pages ## Key Data Flows **ICY Metadata (real-time track info):** Browser → `GET /radio/sse/?url=` → Django SSE view → `icy.py` opens stream → yields `StreamingHttpResponse` events → `app.js` `EventSource` updates UI **Last.fm Scrobbling:** Track recorded via `POST /radio/record/` → `TrackHistory` created → `lastfm.py` scrobbles if user has session key and opt-in enabled **Station Persistence:** All station CRUD is JSON API (save/remove/favorite/notes) consumed by `app.js` — no page reloads ## Static Files WhiteNoise serves static files with `CompressedManifestStaticFilesStorage` (cache-busting hashes). Run `python manage.py collectstatic` before production deployment.