Skip to content

Admin Panel Overview

Location: apps/admin/

Tech stack: Next.js 15 + Ant Design 5 + TanStack Query + React Router v6

The admin panel is a warm parchment-themed SPA (#F7F4ED background) used by moderators and admins for content moderation, user management, governance, and platform analytics.

Base URL: https://admin.regulus.app (Vercel deployment) API base: All calls go to GET /api/v1/admin/* unless noted.


Authentication

Login via POST /identity/login with role = 'admin' or role = 'moderator'. JWT stored in memory (AuthProvider). ProtectedShell redirects to /login when unauthenticated.


Pages

Dashboard (/)

Endpoints used:

  • GET /admin/metrics — cached 30s server-side

Metrics shown:

  • users — total registered users
  • postsTotal — all posts
  • invitesActive — active invite codes
  • reportsOpen — unresolved reports
  • postsHidden — moderator-hidden posts
  • repliesHidden — moderator-hidden replies
  • mauActive — monthly active users

Attention queue: shows when reportsOpen + postsHidden + repliesHidden > 0.


Invite Codes (/invite-codes)

Endpoints: GET /admin/invite-codes, POST /admin/invite-codes/generate, POST /admin/invite-codes/:id/revoke

Columns: code, status, generated by, reserved until, used by, used at, expires at. Actions: Revoke active codes, generate admin-issued codes.


Users (/users + /users/:id)

Endpoints: GET /admin/users, GET /admin/users/:id, POST /admin/users/:id/ban, POST /admin/users/:id/unban, PATCH /admin/users/:id/role

List: id, username, email, role, banned status, created at, post/circle count. User detail (/users/:id):

  • Profile info
  • Role selector (user/moderator/admin)
  • Ban/unban with reason
  • Reputation history
  • Invite tree position
  • Posts list

Circles (/circles)

Endpoints: GET /admin/circles, DELETE /admin/circles/:id

Columns: id, owner, kind, name, member count, created at. Actions: Delete circle (admin only, emits audit log entry).


Posts (/posts)

Endpoints: GET /admin/posts, POST /admin/posts/:id/hide, POST /admin/posts/:id/unhide, DELETE /admin/posts/:id

Columns: title, author, format, interest, visibility, depth, journalism, boost score, reactions, replies, created at, hidden. Filters: format, interest, visibility, journalism, hidden only. Actions: Hide/unhide, soft-delete.


Replies (/replies)

Endpoints: GET /admin/replies, POST /admin/replies/:id/hide, POST /admin/replies/:id/unhide

Columns: body snippet, kind, author, post, created at, hidden. Actions: Hide/unhide.


Reports (/reports)

Endpoints: GET /admin/reports, POST /admin/reports/:id/review, POST /admin/reports/:id/dismiss

Columns: target type/id, reason, reporter, status, created at. Filters: status (open/reviewed/dismissed), target type. Actions: Review (sets reviewed_by + timestamp), Dismiss.


Reputation (/reputation)

Endpoints: GET /admin/reputation/events, POST /admin/reputation/adjust, GET /admin/reputation/appeals, POST /admin/reputation/appeals/:id/resolve

Tabs:

  • Events: Reputation ledger across all users.
  • Adjust: Manual rep adjustment { userId, interestId, delta, note }.
  • Appeals: Pending/accepted/rejected appeals. Resolve with optional restoreDelta.
  • Peer Votes: GET /admin/reputation/votes — view all peer votes for moderation.

Contribution (/contribution)

Endpoints: GET /admin/contribution

Shows top contributors by score. Columns: user, total score, breakdown by kind.


Economy (/economy)

Endpoints: GET /admin/economy/wallets, GET /admin/economy/payments

Tabs:

  • Wallets: All wallets sorted by balance. Columns: user, balance, lifetime_earned, lifetime_spent.
  • Payments: Payment ledger. Columns: sender, receiver, emotion, tier, amount, post, reversed, created at.

Audit Log (/audit-log)

Endpoints: GET /admin/audit-log

All privileged mutations. Columns: action, actor, target_type, target_id, ip, created at. Filters: action type, actor, date range.


Conversations (/conversations)

Endpoints: GET /admin/conversations

Columns: kind, title, member count, message count, created at. Actions: View members (no message content access — privacy).


AI Sessions (/assistant-sessions)

Endpoints: GET /admin/assistant-sessions

Columns: user, topic, status, turn count, started at, completed at.


Discovery Intents (/intents)

Endpoints: GET /admin/intents

Columns: user, intent, note, isActive, updated at.


Media (/media)

Endpoints: GET /admin/media

Columns: owner, bucket, key, mime type, size, status, created at. Actions: Mark as reviewed, soft-delete orphans.


Interests (/interests + /interests/:idOrSlug)

Endpoints: GET /admin/interests, POST /admin/interests, PATCH /admin/interests/:id

List all interests with level, slug, parent, user count. Interest detail: top users by reputation, recent posts, wiki entry.


Series (/series)

Endpoints: GET /admin/series

Columns: title, author, item count, follower count, created at.


Wiki Proposals (/wiki)

Endpoints: GET /admin/wiki/proposals, POST /admin/wiki/proposals/:id/approve, POST /admin/wiki/proposals/:id/reject

Columns: interest, proposer, status, net votes, summary, created at. Actions: Approve (creates new WikiEntry version), Reject.


Settings (/settings)

Endpoints: GET /admin/feature-flags, PATCH /admin/feature-flags/:key

Manage feature flags (e.g., emoji-pay, wiki, personas-ui). Also: broadcast message to all users POST /admin/broadcast { title, body }.


Broadcast Modal

Global button in header for admins. Sends POST /admin/broadcast { title, body }:

  • Creates Notification rows for all non-banned users.
  • Emits admin.broadcast.sent → push fan-out via PushService.

Theme Tokens

typescript
colorPrimary: '#1F1B16'
colorBgBase: '#F7F4ED'     // warm parchment
colorBgContainer: '#FFFFFF'
colorBorder: '#E6DFCF'
Menu.itemSelectedBg: '#EFE9D7'
Table.rowHoverBg: '#EFE9D7'

Regulus — invite-only social-knowledge platform