Web app
Routes, API endpoints, and the dive-stack.
https://soma-ai.cc — Next.js 15 App Router deployed on Vercel.
Authenticated pages
| Route | Kind | What |
|---|---|---|
/app | static | Dashboard home / redirect |
/app/chat | static | Streaming agent chat, useChat + Vercel AI SDK |
/app/capture | static | Quick-add entity (form → memory_capture) |
/app/entities | dynamic | Paginated list with filters + search |
/app/entities/[id] | dynamic | Detail view + dive-stack panels (backlinks, edges, related) |
/app/inbox | static | Recently-ingested sources awaiting action |
/app/timeline | static | Chronological events + facts, Schedule-X views |
/app/projects | dynamic | Kanban over type=project entities |
/app/graph | static | D3 force-directed neighborhood viz |
/app/settings/integrations | dynamic | Google / Slack OAuth + Gmail label subs |
/app/settings/health | static | Apple Health XML import form |
API routes
| Route | Runtime | Purpose |
|---|---|---|
POST /api/chat | nodejs, force-dynamic | Agent stream. 20 req/min/user. 20s stream-start timeout. |
GET,POST,PUT /api/inngest | nodejs, maxDuration=300 | Inngest Cloud workflow handler |
POST /api/telegram/webhook | nodejs, maxDuration=60 | grammY webhook, HMAC-guarded |
POST /api/webhooks/gmail | nodejs | Google Pub/Sub push notification |
POST /api/health/import | nodejs | Apple Health upload → fires health.import event |
GET /api/entities/[id] | nodejs | Fetch one |
POST /api/entities/[id]/archive | nodejs | Soft-delete |
GET /api/events, /api/graph, /api/search | nodejs | Read paths |
GET /connect/google/{start,callback,disconnect} | nodejs | Gmail + Calendar OAuth |
GET /connect/slack/{start,callback} | nodejs | Slack OAuth |
GET /auth/callback / POST /auth/sign-out | nodejs | Supabase Auth |
The dive-stack
The signature interaction. Horizontal stack of panels à la Finder column view. Clicking a backlink, a @mention, or a related entity pushes a new panel on the right. Closing pops it.
Lives under apps/web/src/components/dive/. State is a Zustand store (dive-store.ts). Panel animation is a translateX spring driven by motion/react.
See the Claude skill soma-dive-stack for full implementation guidance.
State management
- Server state — TanStack Query v5 (
@soma/api-client). Queries are keyed by entity id + surface. - UI state — Zustand stores. Each domain gets its own store (
dive-store,command-palette-store, etc.). - URL state —
nuqsfor filter params (type, search, sort).
No global Redux. No Context providers for domain state.
Tailwind + shadcn
Tailwind v4 + @soma/ui (shadcn primitives wrapped with SOMA design tokens). All colors, sizes, spacing come from CSS custom properties defined in packages/ui/src/tokens/*.css. Never hard-code — see soma-design-system skill.