- Add lucide-react for SVG icons throughout the admin
- Redesign sidebar with gradient background, icons per nav item, and sticky layout
- Redesign topbar with cleaner user info display
- Redesign dashboard with icon-backed stat cards, gradient progress bars, activity feed
- Update AdminNavLink with icon support and new active state styling
- Improve table styling in admin-page CSS (rounded corners, hover, spacing)
- Clean up unused admin CSS
- Redesign site header with multi-layer gradient overlays, decorative glows, dot pattern texture, responsive clamp font sizing, and animated ping online badge
- Add glass-dropdown CSS class with 60% opacity backdrop blur (20px) and smooth dropdownIn animation (scale + translate)
- Fix dropdown positioning with top-full for proper alignment under menu triggers
- Standardize all dropdowns (nav, top-header, color picker, language switcher) to use glass-dropdown class
- Reduce dropdown background opacity from 97% to 80% so backdrop-filter is visible
- Add glass-dropdown CSS class with blur(16px) and saturate(180%)
- Add backdrop blur to mobile nav overlay for smoother feel
- Increase photo lightbox backdrop blur from 2px to 8px
- Add background-blend-mode: overlay to site-bg for richer texture
Beyond parity — the web-feasible versions of the "host-only" items plus
extras AtomCMS doesn't have:
- App-level abuse/DDoS guard (src/lib/services/abuse-guard.ts): counts
requests per IP and auto-adds flooders to website_ip_blacklist (enforced
by the access guard) + fires ddosDetected(). OFF by default, tunable via
settings. The iptables layer stays host-only; this is the real app-tier
mitigation. Access guard now also enforces the IP blacklist (cached).
- PWA: a themeable web manifest (src/app/manifest.ts) + a service worker
(public/sw.js, cache-first assets / network-first pages) registered after
hydration — the hotel is now installable.
- /api/health: DB + emulator(RCON) + runtime status probe.
- /developers: a public API documentation page covering every REST endpoint
with its method, path and auth requirement.
- jobs-worker: daily emulator JAR backup (runs host-side in the worker, like
AtomCMS's backup command) — copies + prunes; no-ops unless EMULATOR_JAR_PATH
+ EMULATOR_BACKUP_DIR are set.
Verified live (prod, amx_test): /api/health ok, manifest + sw served, docs
page renders, normal pages unaffected by the guard. tsc 0, vitest 49/49,
next build 0.
- Rich profile (/u/[username]): wallet (credits/duckets/diamonds), friends
grid (messenger_friendships), and owned rooms sections.
- Login history: new website_login_logs table (model + migration 0007),
recorded on every successful sign-in (ip + user-agent), surfaced on a new
/settings/sessions page (with failed-attempt list from failed_logins).
- Photos lightbox + home article slider (client components, no Swiper dep).
- /client/flash launcher (SSO ticket like the Nitro page).
- Admin: private chatlogs section in /admin/logs, /admin/radio/moderation
(shout moderation), a "users by rank" inline bar chart on the dashboard,
and a TinyMCE rich-text editor on the article admin forms.
- Niche API: /api/values/[id], /api/guilds(+/[id]), /api/radio/auto-play.
Verified live (prod, amx_test): login recorded → /settings/sessions shows
it with device; profile renders wallet/friends/rooms; dashboard chart +
private-chat logs + /client/flash + /api/guilds all OK. Reverted test data.
tsc 0, vitest 49/49, next build 0.
Final parity push (web-tier only):
- REST API write + token auth: POST /api/tokens (issue a personal_access_token
for the session user), Bearer auth via src/lib/api-auth.ts, POST
/api/articles/[slug]/comment, GET/DELETE /api/me/tokens, full tickets API
(/api/tickets +[id] +[id]/reply), radio current-dj/points/points-leaderboard/
embed-config + POST shouts, and a real-time /api/radio/stream (SSE). 31 public
API routes total.
- Pages: /draw-badge (buy a custom profile badge → credits + RCON), /me
dashboard (stats + online friends + referral claim). Wired into the nav.
- HTML sanitisation (sanitize-html) — the HTMLPurifier equivalent — applied to
writeable boxes + article bodies before dangerouslySetInnerHTML.
- "Dusk" dark theme preset + a default-dark site option honoured by the
no-flash boot script.
Verified live (prod, amx_test): token issue → Bearer endpoint 200, no-token
401; /api/me/tokens lists it; current-dj/leaderboard JSON; /me + /draw-badge
200; reverted the test user + tokens. tsc 0, vitest 49/49, next build 0.
Phase D of the parity push:
- Radio player: fixed bottom-right widget (port of atom's radio-player.blade)
that streams the hotel radio via <audio>, with play/pause, volume, current
DJ / now-playing and live listener count, polling the public API every 15s.
A server gate (RadioPlayerGate) only mounts it when radio is enabled + a
stream URL is set, so no widget JS ships when off. Mounted in the layout.
- Logo generator (/logo): client tool — hotel name + font/colour/size pickers
with a live preview and "download PNG" via canvas.
- Public room page (/room/[id]): renders an emulator room (name, owner,
users/max, state, category) in a ContentCard.
Verified live (prod, amx_test): /logo renders the generator, /room/50 shows
the real room "Dark Elegant Bundle", and with radio enabled the player
mounts fixed bottom-right (audio + play/pause + Test FM); reverted the test
settings. tsc 0, vitest 49/49, next build 0.