Each user in the leaderboard links to a profile page showing stat cards,
a line chart (requests / storage / watch hours, 1W–1Y timeframes, raw or
normalized, plus a Storage Load mode), and a full request history sorted
newest-first. Includes Overseerr media status codes (1–5), Tautulli watch
history aggregation, and a server-side raw cache so the user API route can
enrich requests without re-fetching everything.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Settings modal (gear icon) lets you configure all service URLs and API
keys from the dashboard; values persist to data/settings.json with
process.env as fallback so existing .env.local setups keep working
- Per-service Test button hits each service's status endpoint and reports
the version on success
- Discord webhook support: structured embeds per alert category (requesters,
approval age, episode progress, watch-rate stats) sent on new/reopened
alerts only — already-open alerts don't re-notify
- Alert detail page restructured: prose descriptions replaced with labelled
fields, episode progress bar for partial TV, watch-rate stat block,
View in Radarr/Sonarr/Seerr action buttons, requester names link to
Overseerr profiles, timestamps moved inline with status
- Tab state is pure client state (no ?tab= in URL); router.back() used
on alert detail for clean browser history
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
After closing or reopening an alert, patch the cached dashboard stats
in localStorage so the summary card and tab badge reflect the new
count immediately when navigating back, without waiting for a refresh.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Thread titleSlug through RadarrMovie/SonarrSeries → MediaEntry →
AlertCandidate, building a direct mediaUrl server-side at alert
generation time (RADARR_URL/movie/slug, SONARR_URL/series/slug)
- Alert detail page: single-column full-width layout, metadata chips
row showing opened/closed dates, media type, and a "View in Radarr/
Sonarr" external link button when available
- Comments section sits below the full-width overview card
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add author field ("user" | "system") to AlertComment
- System comments are automatically added when an alert is reopened
by the engine ("Alert reopened — condition is still active.") or
manually via the UI ("Manually reopened.")
- Alert detail page redesigned with a two-column layout (3/5 detail,
2/5 comments) at lg breakpoint
- System comments render as centered event dividers with a gear icon;
user comments render as avatar + bubble
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When a closed alert reopens (condition still present, no active
cooldown), keep firstSeen and comments intact. The alert is the same
incident continuing — closing and reopening should not erase history.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Content alerts (unfulfilled, pending, tautulli-no-matches) now have
zero cooldown on manual close — they reopen immediately on the next
refresh if the condition still exists. Closing is an acknowledgment
of the current state, not a suppression of future alerts.
User-behavior alerts (ghost, watchrate) keep a cooldown (7 days) so
a single manual close isn't immediately undone by the next refresh.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- UNFULFILLED_MIN_AGE_DAYS → UNFULFILLED_MIN_AGE_HOURS (default 12h)
so new requests don't sit a full 3 days before alerting
- Incomplete Download threshold: 90% → 100% (any missing episode fires)
- PENDING_MIN_AGE_DAYS: 7 → 2
- Ghost Requester reworked: instead of checking lifetime plays = 0,
now checks whether the user's last Tautulli activity predates their
last N (default 5) approved requests — catches people who request
but don't watch their recent content
- Removed Frequent Declines alert
- Add tautulliLastSeen to UserStat to support the ghost rework
- Update README to reflect all changes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Documents setup, environment variables, all alert types with their
tunable parameters and cooldowns, and the alert lifecycle diagram.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Full implementation on top of the Next.js scaffold:
- Leaderboard with per-user request count, storage, avg GB/req, and
optional Tautulli watch stats (plays, watch hours), each with dense
per-metric rank (#N/total)
- SWR cache on /api/stats (5-min stale, force-refresh via button);
client-side localStorage seed so the UI is instant on return visits
- Alerting system: content-centric alerts (unfulfilled downloads,
partial TV downloads, stale pending requests) and user-behavior
alerts (ghost requester, low watch rate, declined streak)
- Partial TV detection: flags ended series with <90% of episodes on disk
- Alert persistence in data/alerts.json with open/closed state,
auto-resolve when condition clears, manual close with per-category
cooldown, and per-alert notes
- Alert detail page rendered as a server component for instant load
- Dark UI with Tailwind v4, severity-colored left borders, summary
cards with icons, sortable leaderboard table
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>