- Credentials provider now resolves two distinct accounts from env:
SUPERADMIN_USERNAME / SUPERADMIN_PASSWORD → role "superadmin"
ADMIN_USERNAME / ADMIN_PASSWORD → role "admin"
The role is carried through the JWT and Session callbacks so the UI
and API can gate on it. Types extended via types/next-auth.d.ts.
- lib/auth.ts exports requireRole(minRole) and sessionRole(session).
- /api/players POST rejects "op" and "deop" with 403 unless the caller
is superadmin. All other player actions (whitelist add/remove, ban,
pardon) remain available to both roles.
- lib/use-role.ts (client hook) exposes role / isSuperadmin / authed
for UI gating without duplicating session typing.
- PlayerManager: Add-OP button and per-row Deop action are hidden or
disabled for non-superadmin; when a regular admin is viewing the
Ops tab, a banner explains the read-only state.
- PlayerDrawer: Make Op / Deop button disabled with tooltip for
non-superadmin; whitelist, ban, pardon unchanged.
- Navbar: subtle role pill next to the user name ("Super" for
superadmin amber-tinted, "Admin" for admin).
- Migration note: the existing ADMIN_* credentials now log in as the
restricted admin role. Set SUPERADMIN_USERNAME + SUPERADMIN_PASSWORD
in .env.local to retain operator-management ability. A placeholder
superadmin account was generated in .env.local; the password is in
the commit terminal output only, not the repo.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- New POST /api/mods/update SSE route: per-file Modrinth lookup → snapshot →
download latest → swap old jar → restart + verify (if server-side) →
rebuild modpack, with automatic rollback on any failure.
- ModManager: "Update" button next to each mod with an available update,
plus "Update all (N)" in the installed list header. Reuses the existing
install timeline UI (same event shape). SSE reader extracted as
consumeSSE helper.
- Error boundaries: app/error.tsx (scoped), app/admin/error.tsx (admin
subtree retry), app/not-found.tsx, app/global-error.tsx (hard-fail
fallback with inline styles, no app shell dependency).
- A11y sweep: aria-pressed + aria-label on LogViewer level chips and
ModManager side filter; aria-label on admin TabsList; skip-to-content
link in Navbar targeting <main id="main"> on public + admin pages;
role/aria-live on install/update timeline; global Esc in ModManager
clears open confirm prompts and exits search/review wizard steps.
- Command palette (cmdk): global Ctrl/⌘+K dialog mounted in Providers.
Navigate admin tabs, toggle theme, start/stop/restart server, create
backup, re-check mod updates, jump to any cached mod/player/snapshot/
backup. Auth-aware — public users see only Home / Log in / Theme.
- AdminTabs listens to hashchange so palette navigation updates the
active tab live.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Admin page split into tabs (Server/Players/Chat/Mods/Backups/Logs) with
hash + localStorage persistence; inactive tabs no longer mount.
- Log viewer: level color-coding, search, level filter chips, auto-scroll
toggle, copy button, visible-line count.
- Installed mods list: search field + side filter (all/both/server/client)
with live count; public ModList gets skeleton + empty states and search.
- Theme toggle with no-flash inline init, localStorage + system preference.
- Layout: full OG / Twitter metadata, title template, keywords,
dual-theme themeColor, metadataBase.
- lib/mods.ts: per-jar mtime+size parse cache (cold 6s -> warm ~45ms on
/api/mods for the full mod list); cache eviction on mod removal.
- ChatBridge polling eased 3s -> 5s with 2s stale window.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Next.js 16 + Tailwind v4 + shadcn v4 dashboard for managing a modded
Forge 1.20.1 server. Includes server controls, player management, mod
manager with Modrinth search and dependency resolution, world backups,
snapshots, analytics, logs, and chat bridge.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>