Visualize your Letterboxd profile data with interactive charts and insights!
Try it live! The server sleeps when idle, so the first load takes a moment to wake up.
- Enter your Letterboxd username (or upload your data export)
- The app scrapes your public profile data (this may take a few minutes)
- Explore interactive visualizations across multiple categories!
| Category | Visualizations |
|---|---|
| Likes & Ratings | Histogram • Donut chart • Scatter plot • Stat tiles |
| Diary Activity | Calendar heatmap • Line charts • Weekday bars |
| Genres & Themes | Bar charts • Radar charts |
| Decades | Radar chart |
| Obscurity Metrics | Histogram • Rarest films list |
| Runtime Analysis | Bar chart |
| People & Studios | Bar charts • Radar chart |
| Languages & Countries | Bar charts • Radar charts |
Visit memento-0fke.onrender.com
Scraping by username is rate limited on hosted servers, so uploading your data export is the more reliable route there. Running locally avoids this entirely.
- Clone the repository:
git clone https://github.com/danielkwan-dev/memento.git cd memento - Start everything:
docker compose up
- Visit localhost:8080
- Start Postgres:
docker compose up -d postgres
- Run the API and the worker:
go run ./cmd/api go run ./cmd/worker
- Run the frontend!
cd web && npm install && npm run dev
- The app only accesses the public Letterboxd data on your profile
- Your ratings and diary entries can be deleted at any time from the dashboard
- Film details are cached and shared between users, so popular films are only fetched once
Backend:
Go • Postgres • goquery
Frontend & Visualizations:
React • TypeScript • Recharts • Tailwind
Infrastructure:
Docker • GitHub Actions • Render • Neon
The API image also serves the built React app, so the whole web tier is one deploy with no CORS to configure.
A few things worth knowing if you run this yourself:
- Letterboxd has no public API, so requests go through a client that replays real browser TLS fingerprints
- Rate limits are per-IP and cumulative, so a long scrape can earn a temporary block that clears on its own
- Uploading your export is more reliable than scraping for large accounts, since it skips the paginated profile pages
- Running it locally works best. Letterboxd treats a home connection far more leniently than a datacenter one, so the hosted demo gets rate limited where a local run does not —
docker compose upand everything works - The free hosting tier sleeps when idle, so the first run after a quiet spell waits a few seconds to wake up (the UI shows this as a real 'waking' phase rather than an unexplained pause)
- The database connection must be direct, not pooled: progress streaming uses
LISTEN/NOTIFY, and PgBouncer in transaction mode (what most managed poolers run) silently drops it
Running the tests:
go test ./...
docker compose up -d postgres
MEMENTO_TEST_DATABASE_URL=postgres://memento:memento@localhost:5432/memento?sslmode=disable go test ./...