learning_ai_common_plat/dashboards/admin-web
2026-03-12 12:27:08 -07:00
..
e2e test(auth): SmartAuth Playwright E2E specs — login, MFA settings, security dashboard, devices, passkeys 2026-03-12 11:13:41 -07:00
public feat(dashboards): migrate admin + tracker dashboards to common-plat as product-agnostic 2026-02-28 02:17:35 -08:00
src fix(auth): address SmartAuth agent review gaps — Swift mock wiring, passkey SDK consistency, device list parity, JSDoc, SSR docs 2026-03-12 12:27:08 -07:00
.bundlesizerc.json feat(dashboards): migrate admin + tracker dashboards to common-plat as product-agnostic 2026-02-28 02:17:35 -08:00
.dockerignore feat(dashboards): migrate admin + tracker dashboards to common-plat as product-agnostic 2026-02-28 02:17:35 -08:00
.env.example feat(auth): SmartAuth admin-web — OAuth proxy, MFA settings, devices, passkeys, security dashboard 2026-03-12 11:13:14 -07:00
.env.local.example feat(dashboards): migrate admin + tracker dashboards to common-plat as product-agnostic 2026-02-28 02:17:35 -08:00
.gitignore feat(dashboards): migrate admin + tracker dashboards to common-plat as product-agnostic 2026-02-28 02:17:35 -08:00
.nvmrc feat(dashboards): migrate admin + tracker dashboards to common-plat as product-agnostic 2026-02-28 02:17:35 -08:00
components.json feat(dashboards): migrate admin + tracker dashboards to common-plat as product-agnostic 2026-02-28 02:17:35 -08:00
Dockerfile feat(dashboards): migrate admin + tracker dashboards to common-plat as product-agnostic 2026-02-28 02:17:35 -08:00
eslint.config.mjs feat(dashboards): migrate admin + tracker dashboards to common-plat as product-agnostic 2026-02-28 02:17:35 -08:00
next.config.ts feat(dashboards): migrate admin + tracker dashboards to common-plat as product-agnostic 2026-02-28 02:17:35 -08:00
package-lock.json feat(dashboards): migrate admin + tracker dashboards to common-plat as product-agnostic 2026-02-28 02:17:35 -08:00
package.json refactor(design-tokens): improve token validator 2026-03-04 18:13:13 -08:00
playwright.config.ts feat(dashboards): migrate admin + tracker dashboards to common-plat as product-agnostic 2026-02-28 02:17:35 -08:00
postcss.config.mjs feat(dashboards): migrate admin + tracker dashboards to common-plat as product-agnostic 2026-02-28 02:17:35 -08:00
README.md feat(dashboards): migrate admin + tracker dashboards to common-plat as product-agnostic 2026-02-28 02:17:35 -08:00
tsconfig.json feat(dashboards): migrate admin + tracker dashboards to common-plat as product-agnostic 2026-02-28 02:17:35 -08:00
vercel.json feat(dashboards): migrate admin + tracker dashboards to common-plat as product-agnostic 2026-02-28 02:17:35 -08:00
vitest.config.ts feat(dashboards): migrate admin + tracker dashboards to common-plat as product-agnostic 2026-02-28 02:17:35 -08:00

Platform Admin Dashboard

Product-agnostic admin console for the ByteLyst platform. Connects directly to Azure Cosmos DB via the @azure/cosmos SDK — no intermediate API server. Set PRODUCT_ID in .env.local to deploy for any product (e.g. lysnrai, chronomind, nomgap, mindlyst).


Tech Stack

Layer Technology
Framework Next.js 16 (App Router, React 19)
Styling TailwindCSS v4 + shadcn/ui (New York style)
Database Azure Cosmos DB (NoSQL, Serverless) — direct SDK
Auth JWT (jose) + bcrypt (bcryptjs), server-side only
Charts Recharts
Icons Lucide React
Language TypeScript 5

Getting Started

npm install
cp .env.local.example .env.local    # Fill in real Azure credentials

npm run dev                         # http://localhost:3001
npm run check                       # TypeScript + ESLint
npm run build                       # Production build

Seed the Database

Creates all Cosmos containers + default admin/viewer users:

curl -X POST "http://localhost:3001/api/seed?secret=<SEED_SECRET>"

Default Logins

Email Password Role
admin@example.com Admin123! Super Admin
viewer@example.com viewer123 Viewer

Environment Variables

Copy .env.local.example.env.local:

Variable Required Description
COSMOS_ENDPOINT Yes Cosmos DB endpoint URL
COSMOS_KEY Yes Cosmos DB primary key
COSMOS_DATABASE No Database name (set per product)
COSMOS_REGION No Region (default: westus2)
JWT_SECRET Yes Shared JWT signing secret
SEED_SECRET Yes Secret for POST /api/seed
AZURE_KEYVAULT_URL No Azure Key Vault URL
AZURE_SPEECH_KEY No Speech service key (for future features)
AZURE_SPEECH_REGION No Speech region
AZURE_OPENAI_ENDPOINT No OpenAI endpoint
AZURE_OPENAI_KEY No OpenAI key
AZURE_OPENAI_DEPLOYMENT No Model deployment name

Pages

Route Description
/ Dashboard overview — KPIs, charts, recent activity
/users User management — search, filter, detail dialogs
/subscriptions Plan management — pricing, features, create plans
/tokens API token management — create, revoke, scopes
/usage Usage analytics — token/request charts, model costs
/audit Audit log — admin actions, security events
/settings Platform config — kill switch, Azure, rate limits, notifications
/login Authentication page

API Routes

All routes are in src/app/api/:

Endpoint Method Description
/api/auth/login POST Authenticate user (email + password → JWT)
/api/auth/me GET Get current user from Bearer token
/api/users GET/POST List/create users
/api/users/[id] GET/PUT/DELETE User CRUD by ID
/api/tokens GET/POST List/create API tokens
/api/usage GET Usage analytics
/api/audit GET Audit log entries
/api/dashboard/stats GET Dashboard KPI statistics
/api/settings/kill-switch GET/PUT Platform kill switch (read/toggle)
/api/seed POST Initialize containers + seed default users

Architecture

src/
├── app/
│   ├── (dashboard)/              # Protected routes (sidebar + auth guard)
│   │   ├── layout.tsx            # Dashboard shell (sidebar, error boundary)
│   │   ├── loading.tsx           # Skeleton loading state
│   │   ├── page.tsx              # Dashboard overview
│   │   ├── users/page.tsx
│   │   ├── subscriptions/page.tsx
│   │   ├── tokens/page.tsx
│   │   ├── usage/page.tsx
│   │   ├── audit/page.tsx
│   │   └── settings/page.tsx     # Includes kill switch toggle
│   ├── api/                      # Next.js API routes → direct Cosmos DB
│   │   ├── auth/login/route.ts
│   │   ├── auth/me/route.ts
│   │   ├── users/route.ts
│   │   ├── users/[id]/route.ts
│   │   ├── tokens/route.ts
│   │   ├── usage/route.ts
│   │   ├── audit/route.ts
│   │   ├── dashboard/stats/route.ts
│   │   ├── settings/kill-switch/route.ts
│   │   └── seed/route.ts
│   ├── login/page.tsx            # Public login page
│   ├── layout.tsx                # Root layout (providers)
│   └── providers.tsx             # Auth + Theme providers
├── components/
│   ├── ui/                       # 16 shadcn/ui primitives (avatar, badge, button, card, etc.)
│   ├── sidebar-nav.tsx           # Responsive sidebar (mobile hamburger)
│   ├── auth-guard.tsx            # Route protection → redirect to /login
│   └── error-boundary.tsx        # Catch page crashes gracefully
└── lib/
    ├── cosmos.ts                 # Cosmos DB client singleton + container registry
    ├── auth-server.ts            # JWT create/verify + bcrypt (server-side only)
    ├── auth-context.tsx          # Client auth provider (localStorage tokens)
    ├── theme-context.tsx         # Dark/light/system mode
    ├── api.ts                    # Client-side API helper functions
    ├── mock-data.ts              # Mock data + types (fallback when Cosmos unavailable)
    ├── utils.ts                  # cn() tailwind merge helper
    └── repositories/             # Direct Cosmos DB CRUD
        ├── users.ts              # getUserById, getUserByEmail, createUser, updateUser
        ├── tokens.ts             # API token CRUD
        ├── audit.ts              # Audit log read/write
        └── usage.ts              # Usage statistics

Cosmos DB Integration

The dashboard connects directly to Cosmos DB — no intermediate backend server.

Pattern:

Page Component → fetch("/api/...") → API Route → Repository → Cosmos SDK → Azure

Key files:

  • lib/cosmos.ts — singleton CosmosClient, getContainer(name), initializeAllContainers()
  • lib/repositories/*.ts — CRUD functions per container
  • lib/auth-server.tsauthenticateUser(), createAccessToken(), verifyToken()

Container definitions (in cosmos.ts):

Container Partition Key TTL
users /id
licenses /userId
transcripts /userId
usage_daily /userId 1 year
settings /userId
audit_log /category 90 days
api_tokens /userId
devices /userId

Kill Switch

The Settings page has a prominent kill switch card at the top:

  • Green = platform active, Red = platform disabled
  • Toggle writes to settings container: { id: "kill_switch", userId: "system", enabled: bool }
  • All apps (desktop, mobile, web) read this document to check platform status

Features

  • Direct Cosmos DB — no middleware, API routes call SDK directly
  • JWT auth — bcrypt password hashing, HS256 JWT tokens
  • Auth guard — redirects to /login if not authenticated
  • Mock fallback — pages fall back to mock data if Cosmos is unavailable
  • Responsive — sidebar collapses to hamburger on mobile
  • Dark mode — toggle in sidebar footer, persisted to localStorage
  • Error boundary — catches page crashes gracefully
  • Kill switch — global platform toggle on Settings page

Docker

docker build -t platform-admin .
docker run -p 3001:3000 --env-file .env.local platform-admin

# Or with docker-compose
docker compose up -d

Development Notes

  • Port: runs on 3001 in dev (3000 may conflict with Docker)
  • shadcn/ui: components are in src/components/ui/, added via npx shadcn@latest add <component>
  • Adding a new API route: create src/app/api/<name>/route.ts, import from @/lib/repositories/*
  • Adding a new page: create src/app/(dashboard)/<name>/page.tsx — auto-protected by auth guard