diff --git a/CLAUDE.md b/CLAUDE.md
index d935591..9783b39 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -3,8 +3,9 @@
Flask dashboard aggregating status from the user's self-hosted media stack
— Sonarr, Radarr, SABnzbd, Tautulli, Prowlarr, Ombi — plus Unraid array
stats and a Rotten Tomatoes "what's popular that I don't have yet" feed.
-Branded "Greendale Media Centre." Runs as one Docker container on the
-user's Unraid home server. Server-side project directory is named
+Branded "Media Centre" — a single neutral, professional dark theme (the
+earlier five novelty themes were removed). Runs as one Docker container on
+the user's Unraid home server. Server-side project directory is still named
`greendale`; the container/repo are named `arr-summary`.
## Architecture
@@ -33,10 +34,20 @@ user's Unraid home server. Server-side project directory is named
`BeautifulSoup`, JSON-LD parsing), not via an official API — brittle
to upstream HTML changes by nature.
- **`templates/`** — Jinja2 templates (`dashboard.html`, `login.html`,
- `settings.html`); duplicated at the top level too (`dashboard.html` etc.
- outside `templates/`) — appears to be a leftover from an earlier project
- layout or the `export-to-unraid.sh` tooling. Left as-is rather than
- restructured without confirming with the user first.
+ `settings.html`). Stale duplicates of these once sat at the repo root;
+ they were never rendered (Flask loads from `templates/`) and were deleted
+ during the redesign.
+ - All three share one token set defined on `:root` — surfaces, a 6-step
+ `--fs-*` type scale, semantic colours, and `--tap: 44px` for minimum
+ touch targets. Add new UI with those tokens rather than literal values.
+ - `dashboard.html` is ordered by urgency, deliberately mirroring the cache
+ tiers in `app.py`: a "Right now" strip (live streams, download queue,
+ array usage) sits above the fold, with library, discovery, requests and
+ watch insights below it.
+ - Degraded services render through the `service_error()` macro, which
+ pairs `friendly_error` (human cause) with the raw exception behind a
+ disclosure, passed through `redact_secrets` — SABnzbd and Tautulli put
+ their API key in the request URL, so it appears in raw tracebacks.
- **`export-to-unraid.sh`** — a pre-existing standalone deploy script
(build image locally → tarball → rsync + `docker load` over SSH) that
predates the Forgejo pipeline below. Still present, not removed, but the
@@ -78,5 +89,5 @@ pipeline mechanics. Push to `main` on the `forgejo` remote
and `LOGIN_PASSWORD` — this project was already doing this correctly
before the Forgejo migration (compose file uses `${VAR}` substitution from
`.env`, no hardcoded secrets), unlike `n64-tracker` which needed fixing.
-`settings.json` (timezone, theme, changed login password) also persists
+`settings.json` (timezone, changed login password) also persists
server-side outside git.
diff --git a/app.py b/app.py
index 0d44548..e95eb4b 100644
--- a/app.py
+++ b/app.py
@@ -1001,7 +1001,6 @@ def dashboard():
s = load_settings()
timezone = s.get("timezone", "America/New_York")
- theme = s.get("theme", "community")
# Public-facing URLs for card header links (via NPM reverse proxy)
arr_host_public = f"https://hippofam.com"
service_urls = {
@@ -1020,7 +1019,6 @@ def dashboard():
rt_movies=rt_movies, rt_tv=rt_tv,
sonarr_titles=sonarr_titles, radarr_titles=radarr_titles,
timezone=timezone,
- theme=theme,
service_urls=service_urls,
)
@@ -1243,7 +1241,6 @@ def settings_page():
prowlarr_api_key=PROWLARR_API_KEY,
ombi_api_key=OMBI_API_KEY,
arr_host=os.environ.get("ARR_HOST", ""),
- theme=s.get("theme", "community"),
)
@@ -1252,7 +1249,7 @@ def settings_page():
def api_save_settings():
data = request.get_json()
allowed = {"timezone", "sonarr_api_key", "radarr_api_key", "sabnzbd_api_key",
- "tautulli_api_key", "prowlarr_api_key", "ombi_api_key", "arr_host", "theme"}
+ "tautulli_api_key", "prowlarr_api_key", "ombi_api_key", "arr_host"}
filtered = {k: v for k, v in data.items() if k in allowed}
save_settings(filtered)
return jsonify({"success": True})
@@ -1264,7 +1261,6 @@ def api_get_settings():
s = load_settings()
return jsonify({
"timezone": s.get("timezone", "America/New_York"),
- "theme": s.get("theme", "community"),
})
diff --git a/dashboard.html b/dashboard.html
deleted file mode 100644
index 46e2979..0000000
--- a/dashboard.html
+++ /dev/null
@@ -1,1964 +0,0 @@
-
-
-
- {% if up and tautulli.sessions %}
- {% for s in tautulli.sessions %}
-
- {{ '🎬' if s.media_type == 'movie' else '📺' }}
-
-
{{ s.title }}
-
{{ s.user }}
-
-
- {% endfor %}
- {% else %}
-
No active streams
- {% endif %}
-
-
-
-
-
-
—
-
- {% if theme == 'office' %}Dunder Mifflin HQ
- {% elif theme == 'parks' %}Pawnee City Hall
- {% elif theme == 'potter' %}Hogwarts Great Hall
- {% elif theme == 'starwars' %}Death Star Control Room
- {% else %}Study Room F{% endif %}
- · ⚙ Settings
-
-
-
-
-
-
-
- {% if theme == 'office' %}
- 📋 Monday morning meeting: checking downloads, missing episodes, and who took the last of the coffee.
- {% elif theme == 'parks' %}
- 📋 Today's agenda: checking what's missing, what's downloading, and making Pawnee great again.
- {% elif theme == 'potter' %}
- 📋 Today's scroll: checking what spells are missing, what's being conjured, and what deserves a watch.
- {% elif theme == 'starwars' %}
- 📋 Rebel briefing: checking what's missing, what's downloading, and what the Force recommends watching.
- {% else %}
- 📋 Today's agenda: checking what's missing, what's downloading, and what deserves to be watched.
- {% endif %}
-
- {% if theme == 'office' %}
- 📋 Monday morning meeting: checking downloads, missing episodes, and who took the last of the coffee.
- {% elif theme == 'parks' %}
- 📋 Today's agenda: checking what's missing, what's downloading, and making Pawnee great again.
- {% elif theme == 'potter' %}
- 📋 Today's scroll: checking what spells are missing, what's being conjured, and what deserves a watch.
- {% elif theme == 'starwars' %}
- 📋 Rebel briefing: checking what's missing, what's downloading, and what the Force recommends watching.
- {% else %}
- 📋 Today's agenda: checking what's missing, what's downloading, and what deserves to be watched.
- {% endif %}
-