From 4279408876268f4960c98492d3814f5475e36e38 Mon Sep 17 00:00:00 2001 From: Tyler Hoang Date: Tue, 12 May 2026 03:15:17 -0700 Subject: Add stats totals, runtime summary, and duplicate detection on add form - Stats page now shows total films watched and total runtime (formatted as Xd Yh) in an overview panel above the world map - /stats/data endpoint includes total_runtime_minutes in payload - New GET /films/find endpoint returns all shelf matches for a tmdb_id - Add film form shows an inline notice when the selected TMDB film is already logged, with shelf name, date, and a link to the entry - Update CLAUDE.md and README to reflect current auth, OMDb, and router/service structure Co-Authored-By: Claude Sonnet 4.6 --- CLAUDE.md | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'CLAUDE.md') diff --git a/CLAUDE.md b/CLAUDE.md index a646370..ed960f2 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -3,7 +3,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## What This Is -Lumiere is a personal cinema diary — a server-rendered FastAPI web app backed by SQLite. Users track films across three shelves: `diary`, `queue`, and `abandoned`. TMDB enriches film metadata (posters, directors, runtime, countries). +Lumière is a personal cinema diary — a server-rendered FastAPI web app backed by SQLite. A single owner logs in with a password; the `/tyler` public profile is read-only for guests. Films live on three shelves: `diary`, `queue`, and `abandoned`. TMDB enriches metadata (posters, directors, runtime, countries, cast, overview); OMDb supplies third-party ratings (IMDb, Rotten Tomatoes, Metacritic) on the detail page. ## Commands @@ -22,22 +22,34 @@ python -m venv .venv .venv/bin/pytest ``` -Requires a `.env` file with `TMDB_API_KEY=...`. App runs at `http://127.0.0.1:8000`. +Requires a `.env` file with: +``` +TMDB_API_KEY=... +OMDB_API_KEY=... # for IMDb/RT/Metacritic ratings +OWNER_PASSWORD_HASH=... # argon2 hash; generate with: python -c "from argon2 import PasswordHasher; print(PasswordHasher().hash('your-password'))" +SESSION_SECRET=... # random secret for cookie signing +``` +App runs at `http://127.0.0.1:8000`. ## Architecture **Request flow:** Browser → FastAPI router → SQLAlchemy (SQLite) → Jinja2 template → HTML response. `static/app.js` handles star ratings (JSON PATCH) and TMDB search autocomplete without a build step. **Key files:** -- `main.py` — app entry, router registration +- `main.py` — app entry, router registration, `AuthMiddleware` (session-based, password protected) - `database.py` — SQLite engine, sessions, self-healing schema migration (no Alembic; renames old table on column mismatch and migrates data) - `models.py` — single `Film` ORM model with a `shelf` column -- `routers/films.py` — shelf listing, CRUD, director page, queue random pick, star rating API +- `routers/films.py` — shelf listing, CRUD, director page, queue random pick, star rating API, infinite-scroll partial - `routers/imports.py` — Letterboxd and watchlist CSV import, deduplication, enrichment - `routers/stats.py` — all-time stats and year-in-review (pure Python aggregation, no SQL GROUP BY) +- `routers/auth.py` — `/login` / `/logout` using argon2 password hashing +- `routers/profile.py` — public `/tyler` profile page (no auth required) +- `routers/about.py` — static about page - `routers/tmdb.py` — `/tmdb/search?q=` proxy for JS autocomplete -- `services/tmdb.py` — TMDB API client: search, detail fetch, metadata application +- `services/tmdb.py` — TMDB API client: search, detail fetch, metadata application, director bio/image +- `services/omdb.py` — OMDb API client: fetches IMDb/Rotten Tomatoes/Metacritic ratings for detail page - `services/film_people.py` — director name normalization and URL slug helpers +- `services/countries.py` — ISO numeric country code mapping for stats world map **Patterns:** - Route logic stays in `routers/`, shared service logic in `services/` -- cgit v1.3-2-g0d8e