learning_ai_common_plat/dashboards/admin-web
saravanakumardb1 eed654418e fix(admin-web/eslint): hoist .cjs ignore to index-0 ignores block
The previous fix (commit a4ee36b6) added '.pnpmfile.cjs' to the
globalIgnores() call at the END of the admin-web eslint config,
but flat-config v9 only applies ignores from the FIRST config
object that contains an 'ignores' key — every subsequent config
item is matched against the file before the late ignore is read.
That's why CI run 66 still failed with the same require() error
even after the dashboard-level ignore was in place.

Fix: declare an explicit '{ ignores: [...] }' at array index 0,
which is the documented eslint v9 pattern for skipping files
before any rule config attaches:

  defineConfig([
    { ignores: ['**/.pnpmfile.cjs', '**/*.cjs'] },  // <-- now first
    ...nextVitals,
    ...nextTs,
    { rules: { ... } },
    globalIgnores([ ... ]),
  ])

Verified locally:
  cd dashboards/admin-web && npx eslint .  -> 0 errors, 0 warnings
2026-05-23 17:15:34 -07:00
..
e2e chore(admin-web): clear repo-wide lint errors 2026-04-04 17:50:20 -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(admin-web): replace useAuth-getAccessToken with localStorage helper 2026-05-23 15:03:02 -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(runtime): add Cowork checkpoint drill-in 2026-04-04 17:29:12 -07:00
.env.local.example feat(runtime): add Cowork checkpoint drill-in 2026-04-04 17:29:12 -07: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
.pnpmfile.cjs feat(admin-web): add UX foundation - local package resolution and design tokens 2026-05-11 01:51:47 +00: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(admin-web): adopt trading web deployment model with docker-compose 2026-05-11 03:24:33 +00:00
eslint.config.mjs fix(admin-web/eslint): hoist .cjs ignore to index-0 ignores block 2026-05-23 17:15:34 -07:00
next.config.ts fix(platform): production readiness — admin-web client bundling, config sub-path exports, stale tests 2026-03-12 16:49:15 -07: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 feat(platform): add /devops page with platform common devops package 2026-05-11 03:38:06 +00: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