# Psyche — Systems Deep Dive

> The `apps/psyche/` area: a single Next.js 14 admin application — branded
> **Serwaa** in its UI — for managing the Psyche AI virtual-assistant /
> personalization platform (personas, sessions, knowledge base, analytics).

## What this area is

`apps/psyche/` is the application tier of the **Psyche** domain. Today it holds
exactly one tracked Nx project, `psyche-admin` (package `@psyche/admin`), plus a
top-level `apps/psyche/.gitkeep` placeholder reserving room for siblings that do
not yet exist. So the "area" is, in practice, this one admin dashboard.

`psyche-admin` is a real, substantial Next.js 14.2 App Router application
(`apps/psyche/admin`), not a scaffold. It is the operator console for an AI
virtual-assistant product: the README and `src/app/dashboard/` route tree cover
**Personas** (create/configure AI personas — personality on a Big-Five model,
expertise, voice, avatar), **Sessions** (monitor meeting sessions across Zoom /
Teams / Meet / Webex), a **Knowledge Base** (document upload for RAG),
**Analytics** (Recharts dashboards), **Tools**, and **Settings**. The project
carries the tags `scope:psyche`, `layer:app`, `type:nextjs`, `platform:web`
(`apps/psyche/admin/project.json`).

A naming wrinkle worth flagging up front: the Nx project is `psyche-admin` and
the npm package is `@psyche/admin`, but the **user-facing brand is "Serwaa."**
The root layout sets the page title to "Serwaa Admin Dashboard"
(`src/app/layout.tsx`), the sign-in screen shows a "Serwaa" wordmark
(`src/app/auth/signin/page.tsx`), the Zustand auth store persists under the key
`serwaa-auth` (`src/stores/auth-store.ts`), and the API client's header comment
calls its backend the "Serwaa API Gateway" (`src/api/client.ts`). Psyche is the
domain; Serwaa is what this app calls itself to its users.

The stack is conventional and real: Next.js App Router with a `dashboard/`
segment, **Radix UI** primitives wrapped into a local design system under
`src/components/ui/` (~30 components — button, dialog, table, toast, etc.),
Tailwind CSS, **Zustand** for auth state, **TanStack React Query** for server
state (configured in `src/app/providers.tsx`), React Hook Form + Zod for forms,
and `next-themes` for light/dark. Testing is Vitest plus a Playwright visual
regression spec (`tests/visual/auth-signin.spec.ts` with a committed snapshot).

## How it fits the wider system

`psyche-admin` is a **client of a backend it does not contain.** It talks to the
Serwaa API Gateway over REST at `NEXT_PUBLIC_API_URL` (default
`http://localhost:8000`) and expects a WebSocket endpoint at
`NEXT_PUBLIC_WS_URL` for real-time updates. The typed surface of that contract
lives in the `api` object of `src/api/client.ts`: REST resources under
`/api/v1/...` for `sessions`, `personas`, `knowledge`, `tools`, `webhooks`,
`auth`, and `health`. The backend that serves those routes is not part of this
Nx project — this area is purely the web front end.

The boundary is currently **half-wired, and the page is honest about which
half.** The infrastructure seams are real: the sign-in flow performs an actual
`POST /api/v1/auth/signin` through the typed client, persists the returned
bearer token in `localStorage`, and hydrates the auth store
(`src/app/auth/signin/page.tsx`, tagged `V1-P2-1036`); every subsequent request
attaches `Authorization: Bearer …` via `getAuthHeaders()`. But several dashboard
list/detail screens still render **hardcoded mock data** rather than calling
that client — e.g. the personas screen filters and paginates an inline
`mockPersonas` array (`src/app/dashboard/personas/page.tsx`) and the dashboard
overview hardcodes its stat cards and activity feed
(`src/app/dashboard/page.tsx`). So the API client, auth, providers, UI kit, and
accessibility layer are production-grade, while the data-fetching wiring for
most resource pages is still UI-mock pending backend integration. Consumers of
this area are human operators of the Psyche/Serwaa platform; its only code
dependency is the HTTP/WS contract above.

## Entity reference

### psyche-admin

The Psyche domain's web admin dashboard (`apps/psyche/admin`; Nx project
`psyche-admin`, package `@psyche/admin`), branded **Serwaa** in its UI. It is a
Next.js 14.2 App Router application — `projectType: "application"`, tags
`scope:psyche` / `layer:app` / `type:nextjs` / `platform:web` — with the full Nx
target set wired in `project.json` (`dev`/`build`/`start` over `next`, plus
`lint`, `typecheck`, `test` via Vitest, `test-visual` via Playwright, `analyze`,
and `docker-build`/`docker-run`).

What is genuinely implemented: a typed REST client over the Serwaa API Gateway
with a custom `ApiError`, query-string and auth-header helpers, and resource
namespaces for sessions/personas/knowledge/tools/webhooks/auth/health
(`src/api/client.ts`); a persisted Zustand auth store keyed `serwaa-auth`
(`src/stores/auth-store.ts`) and a working `POST /api/v1/auth/signin` sign-in
flow with bearer-token persistence; a React Query + `next-themes` + Toaster
provider tree (`src/app/providers.tsx`); a ~30-component Radix-based design
system under `src/components/ui/`; and a notably real **accessibility layer** —
`voice-commands/`, `captions/`, and `audio-description/` providers. The voice
commands provider (`src/components/voice-commands/voice-commands-provider.tsx`)
is a real Web Speech API integration: it declares the `SpeechRecognition` types,
requests mic permission via `getUserMedia`, runs a `useReducer` state machine,
matches transcripts against a default command set (mute, leave, screen-share,
captions, etc.), drives a confirmation flow for destructive commands, and
dispatches to an injected `meetingController` — its `simulateCommand` helper is
an explicitly-labelled testing affordance, not a fake execution path.

Where it is honest about being incomplete: many dashboard resource pages render
inline mock data instead of calling the API client —
`src/app/dashboard/personas/page.tsx` filters/paginates a hardcoded
`mockPersonas` array, and `src/app/dashboard/page.tsx` hardcodes its stat cards
and activity feed. The typed client exists and works (sign-in proves the seam
end-to-end), but the data wiring for most list/detail screens is pending backend
integration. In short: real app shell, real auth, real client, real
accessibility/voice subsystem; resource pages still on UI mocks.
