Your year in Plex, wrapped - a Spotify-Wrapped-style recap of your watch history, built from Tautulli stats.
  • C# 81.6%
  • HTML 12.9%
  • CSS 5.2%
  • Dockerfile 0.3%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
CheapNud b02c9155b1
All checks were successful
Build & Test / Build and Test (push) Successful in 2m19s
Build, Push & Deploy / Build and Test (push) Successful in 1m35s
Build, Push & Deploy / Build & Push Docker Image (push) Successful in 40s
Build, Push & Deploy / Deploy to the app host (push) Successful in 13s
Trust forwarded headers from the reverse proxy
2026-08-29 15:12:58 +02:00
.forgejo/workflows Show posters, backdrops and title facts on the story cards, add the app version 2026-08-24 23:49:21 +02:00
.github/workflows Publish to the Forgejo registry instead of GHCR 2026-08-09 17:24:04 +02:00
CheapWrapped.Tests Show posters, backdrops and title facts on the story cards, add the app version 2026-08-24 23:49:21 +02:00
Components Show posters, backdrops and title facts on the story cards, add the app version 2026-08-24 23:49:21 +02:00
Content Persist Plex metadata and add four stats from the old wrapped 2026-08-04 15:10:25 +02:00
Data Persist Plex metadata and add four stats from the old wrapped 2026-08-04 15:10:25 +02:00
Migrations Show posters, backdrops and title facts on the story cards, add the app version 2026-08-24 23:49:21 +02:00
Models Show posters, backdrops and title facts on the story cards, add the app version 2026-08-24 23:49:21 +02:00
Properties Scaffold Blazor Server app 2026-07-30 03:33:20 +02:00
Services Refresh cached metadata rows that predate the title facts 2026-08-24 23:50:08 +02:00
wwwroot Show posters, backdrops and title facts on the story cards, add the app version 2026-08-24 23:49:21 +02:00
.dockerignore Initial scaffold: README, build plan, CI workflows, project hygiene 2026-07-28 17:35:07 +02:00
.env.example Trust forwarded headers from the reverse proxy 2026-08-29 15:12:58 +02:00
.gitattributes Initial scaffold: README, build plan, CI workflows, project hygiene 2026-07-28 17:35:07 +02:00
.gitignore Prepare the deployment 2026-08-04 15:38:46 +02:00
appsettings.Development.json Scaffold Blazor Server app 2026-07-30 03:33:20 +02:00
appsettings.json Gate the wrapped behind Plex sign-in 2026-08-04 14:22:59 +02:00
AppVersion.cs Show posters, backdrops and title facts on the story cards, add the app version 2026-08-24 23:49:21 +02:00
CheapWrapped.csproj Add Tautulli API client 2026-07-30 04:15:07 +02:00
CheapWrapped.slnx Add Tautulli API client 2026-07-30 04:15:07 +02:00
docker-compose.yml Trust forwarded headers from the reverse proxy 2026-08-29 15:12:58 +02:00
Dockerfile Show posters, backdrops and title facts on the story cards, add the app version 2026-08-24 23:49:21 +02:00
LICENSE Initial scaffold: README, build plan, CI workflows, project hygiene 2026-07-28 17:35:07 +02:00
Program.cs Trust forwarded headers from the reverse proxy 2026-08-29 15:12:58 +02:00
README.md Move workflows to .forgejo 2026-08-12 11:35:13 +02:00
TODO.md Note the runner cache race and the stale replica remote 2026-08-24 23:31:47 +02:00

CheapWrapped

Your year in Plex, wrapped — a playful "Spotify Wrapped"-style recap of your watch history, built from Tautulli stats with zero runtime AI cost.

Status: early development / README-driven. See TODO.md for the full build plan.

What it is

An end-of-year (and on-demand) viewing recap for Plex users: total watch time, top shows and movies, genres, binges, night-owl patterns, streaks — presented as a scrollable, animated, shareable story of cards, badges, and witty one-liners.

The fun does not come from a live LLM call per user. It comes from a large, hand-authored content library — a badge taxonomy, viewer archetypes, and a categorized copy bank with interpolation — that gets selected and filled by each user's real stats. No per-user API bill, no user-supplied API keys, no external dependency at run time. Deterministic, tunable, and every line is reviewable before it ships.

Inspired by Wrapperr (the data model) and plexwrap (the fun), but replacing plexwrap's runtime ChatGPT dependency with a build-time content engine.

Features (planned)

  • The Wrapped story — Spotify-Wrapped-style card sequence: totals → top titles → genres → archetype → badges → shareable summary
  • Badge / achievement system — dozens of stat-triggered badges (Night Owl, The Completionist, Serial Abandoner, Threat Level Midnight…)
  • Viewer archetypes — a "personality" assigned from watch behaviour (genre mix, time-of-day, binge/abandon patterns), no LLM
  • Witty copy engine — categorized, interpolated one-liners filled from real stats
  • Plex SSO — sign in with Plex, restricted to server friends (PIN-based, same pattern as CheapNights)
  • Shareable cards — export/permalink a card or the full wrapped
  • Per-user + server-wide recaps, any date range (not just year-end)

Tech Stack

  • C# 15 / .NET 11 — Blazor Server, interactive rendering
  • MudBlazor — component library + theming (the pretty cards)
  • EF Core — SQLite (dev) / PostgreSQL (prod)
  • CheapHelpers — EF repos, Blazor selectors, caching, Plex auth
  • Tautulli API — watch-history source
  • Docker — built and published to the Forgejo container registry

Repo & sync topology

Forgejo is the forge, and everything runs there — source, CI, container registry and deploy. This matches Voltiq and CheapFleet; the ecosystem's other model is GitHub-primary with a Forgejo mirror (CheapTasks, CheapNights).

  • Source of truth, build/test/PR-review, image registry and deploy: Forgejo (.forgejo/workflows, SINK act_runner)
  • No GitHub repo exists for this project. The two .github/workflows files are inert until one does — see TODO if a backup mirror is still wanted

Development

dotnet run                                   # SQLite, auto-creates the dev db
dotnet user-secrets set "Plex:AdminToken" "…"
dotnet user-secrets set "Tautulli:ApiKey" "…"

CI/CD

  • .forgejo/build.yml — build + test on pull requests and pushes to master
  • .forgejo/deploy.yml — on a v*.*.* tag: build + test, push the image to the Forgejo registry, then deploy over SSH. Tagging is the release action; merging deploys nothing
  • .forgejo/pr-review.yml — automated PR review
  • .github/codeql.yml / dependency-review.yml — only run if a GitHub mirror is ever set up

License

See LICENSE.