Admin Dashboard

The Admin Dashboard provides site-wide administration capabilities for managing users, teams, and viewing usage analytics.

Configuration

Site administrators are configured via the admin section in config/app.config.ts:

admin: {
  emails: [
    'admin@example.com',
    'another-admin@example.com',
  ],
}

Users whose email addresses are in this list will see the "Admin" link in the sidebar and have access to all admin features.

Admin Access

Admin access is granted if the user meets either condition:

  • Their email is listed in config.admin.emails (case-insensitive)
  • They have isAdmin: true in the database (legacy support)

Admin Pages

Dashboard (/admin)

The main admin dashboard displays:

  • Stats Cards: Total users, teams, threads, messages, and recent activity
  • Usage Chart: Visual chart showing messages and token usage over time
    • Period selector: 7, 30, or 90 days
    • Metric selector: Messages, Input Tokens, Output Tokens, Total Tokens
    • Summary row with total, daily average, and peak day
  • Plan Distribution: Breakdown of users by subscription plan
  • Recent Feedback: Latest user feedback on AI responses

Navigation links to Manage Users and Manage Teams (if teams enabled).

User Management (/admin/users)

Lists all users in the system with:

ColumnDescription
UserName, email, avatar, OAuth provider
PlanDropdown to change user's subscription plan
MessagesMessage count this month
TeamsClickable pills showing team memberships with roles
AdminToggle button to grant/revoke database admin flag
JoinedAccount creation date

Features:

  • Search: Filter users by email or name
  • Pagination: Navigate through large user lists
  • Team Links: Click a team pill to view that team's details

Team Management (/admin/teams)

Lists all teams in the system (only visible if teams are enabled):

ColumnDescription
TeamTeam name and avatar
MembersNumber of team members
ThreadsNumber of team threads
CreatedTeam creation date

Features:

  • Search: Filter teams by name
  • Pagination: Navigate through large team lists
  • Click to View: Click any team row to see team details

Team Details (/admin/teams/:teamId)

Displays detailed information about a specific team:

  • Stats: Member count, thread count, creation date
  • Team Context: The AI context configured for team conversations
  • Members List: All team members with:
    • Name and email (clickable to search in user management)
    • Role badge (owner, admin, member, viewer)
    • Join date

Waitlist (/admin/waitlist)

Provides a basic waitlist table with invite actions.

Features:

  • List: Email, name, status, created date
  • Invite: Generates a single-use invite token and optionally emails it

Promo Codes (/admin/promo-codes)

Provides a lightweight promo code manager.

Features:

  • Create: Code, credits, max uses, start/end window, credit expiry
  • Search: Filter by code
  • Status filter: Active, scheduled, expired
  • Deactivate/Reactivate: Toggle availability by setting endsAt
  • Copy: Copy promo code to clipboard

API Endpoints

All admin endpoints require authentication and admin access.

Stats & Analytics

MethodEndpointDescription
GET/api/admin/statsDashboard statistics
GET/api/admin/usageUsage data over time
GET/api/admin/feedbackFeedback statistics and recent items

Usage Query Parameters:

ParameterTypeDefaultDescription
daysnumber30Number of days of data (1-365)

User Management

MethodEndpointDescription
GET/api/admin/usersPaginated user list
PATCH/api/admin/users/:userIdUpdate user (plan, isAdmin)

User List Query Parameters:

ParameterTypeDefaultDescription
pagenumber1Page number
pageSizenumber20Users per page (max 100)
searchstring-Filter by email or name

User Update Body:

{
  isAdmin?: boolean;  // Grant or revoke admin status
  plan?: string;      // Change subscription plan
}

Team Management

MethodEndpointDescription
GET/api/admin/teamsPaginated team list
GET/api/admin/teams/:teamIdTeam details with members

Team List Query Parameters:

ParameterTypeDefaultDescription
pagenumber1Page number
pageSizenumber20Teams per page (max 100)
searchstring-Filter by team name
includeArchivedbooleanfalseInclude archived teams

Waitlist

MethodEndpointDescription
GET/api/admin/waitlistList waitlist entries
POST/api/admin/waitlist/:id/inviteInvite waitlist entry

Promo Codes

MethodEndpointDescription
GET/api/admin/promo-codesList promo codes
POST/api/admin/promo-codesCreate promo code
PATCH/api/admin/promo-codes/:idUpdate promo code

Response Types

AdminStats

interface AdminStats {
  totalUsers: number;
  totalTeams: number;
  totalThreads: number;
  totalMessages: number;
  planDistribution: Record<string, number>;
  newUsersLast30Days: number;
  messagesLast30Days: number;
}

UsageDataPoint

interface UsageDataPoint {
  date: string;        // "2024-01-15"
  messages: number;    // Count of messages
  inputTokens: number; // Total input tokens
  outputTokens: number;// Total output tokens
}

AdminUser

interface AdminUser {
  id: string;
  email: string;
  name?: string | null;
  avatarUrl?: string | null;
  isAdmin: boolean;
  plan: string;
  messagesThisMonth: number;
  credits: number;
  emailVerified: boolean;
  oauthProvider?: string | null;
  createdAt: Date;
  threadCount: number;
  teamCount: number;
  teams: AdminUserTeam[];
}

interface AdminUserTeam {
  id: string;
  name: string;
  role: string;
}

AdminTeam / AdminTeamDetails

interface AdminTeam {
  id: string;
  name: string;
  memberCount: number;
  threadCount: number;
  createdAt: Date;
  archivedAt?: Date | null;
}

interface AdminTeamDetails extends AdminTeam {
  context?: string | null;
  members: AdminTeamMember[];
}

interface AdminTeamMember {
  id: string;
  email: string;
  name?: string | null;
  avatarUrl?: string | null;
  role: string;
  joinedAt: Date;
}

Security Considerations

  1. Config-based access: Admin emails are defined in server configuration, not user-editable
  2. Case-insensitive matching: Email comparison is case-insensitive
  3. Self-protection: Users cannot remove their own admin status
  4. Audit trail: All user changes are logged with timestamps
  5. No destructive actions: Admin can modify users but cannot delete accounts (preserves data integrity)

Extending Admin Features

To add custom admin functionality:

  1. Add API endpoints in packages/server/src/api/admin.ts
  2. Add types in packages/shared/src/types/admin.ts
  3. Create pages in packages/client/src/pages/Admin*.tsx
  4. Add routes in packages/client/src/App.tsx wrapped with <AdminRoute>

Example adding a new admin page:

// App.tsx
<Route
  path="/admin/custom"
  element={
    <AdminRoute>
      <AdminCustomPage />
    </AdminRoute>
  }
/>

The AdminRoute component handles authentication and admin access verification.