- Replace Prisma client runtime with Drizzle ORM (zero Prisma engine/query engine in production)
- Add Prisma-compatible facade (@/lib/prisma-facade.ts) backed by Drizzle for backwards compatibility
- Runtime queries route through Drizzle ORM; @prisma/client is now devDependency (types only)
- Remove @prisma/adapter-mariadb dependency; delete prisma-pool.ts and types/prisma.ts
- New Drizzle schema layer: src/db/schema.ts (176 tables) and src/lib/db.ts (connection)
- Update README documenting the dual-layer ORM architecture
- Restore src/generated/ gitignore (build artifact for local type generation)
- 0 TypeScript errors, 583 tests passing
The facade intentionally uses `any` types to match the Prisma Client API surface,
allowing existing code to run unmodified while routing queries through Drizzle at runtime.
Wire orphan routes into hub tabs, group Radio into primary/tools rows, show theme/language once on desktop, and remove duplicate page titles under AdminHubChrome.
Co-authored-by: Cursor <[email protected]>
- 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
Swept the whole housekeeping panel (34 pages) so it's a consistent,
improved adaptation of the old Filament admin rather than bare tables:
- Live status tiles (StatusCard) summarising each page's data — counts
and stateful metrics (users online, active/permanent bans, pending
applications, settings, radio shouts, etc.).
- Status pills (admin-badge ok/danger) replacing ad-hoc text: online/
offline, account/ip ban types, permanent vs timed, command OK/FAIL,
alert severity & read/new, enabled/disabled, open/closed.
- Sections wrapped in .admin-section with h2 headers; redundant inline
table styling removed (the global .admin layer handles it).
- alerts/logs/emulator hand-built as the reference pattern; the rest
via parallel agents that read the schema and preserved every server
action, query and field name.
Behaviour unchanged (same actions, queries, field names). Verified in a
real authed admin session (prod, amx_test): pages render with live data
(Users tiles show 7 real accounts + online/offline pills), no errors.
tsc 0, vitest 49/49, next build 0.
/news and six admin pages issued raw prisma reads with no try/catch, so
a DB outage rendered a 500 instead of an empty state. Wrap each read
(try/catch or .catch(() => fallback), preserving select() row types and
notFound() on the user-detail page). Matches the fail-soft pattern used
across the rest of the app.
Verified: tsc 0, next build 0, all public pages 200 against a dead DB.