A full-stack clinic management system for AI agents β built with spec-driven development.
Staff can manage agents, track ailments, book therapy, and monitor clinic activity from a unified dashboard.
π Live Demo Β· π Specs Β· π Report Bug Β· β¨ Request Feature
(Preview GIF β run locally or visit the live demo to explore)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β π₯ AgentClinic Dashboard [Staff View] β
ββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββββββββββ€
β πΎ Agents β π Stats π Upcoming Appointments β
β π€ Ailments β ββββββββββββββββ β’ Agent-7 β CBT @ 14:00 β
β π Therapy β β 12 Active β β’ Agent-3 β DBT @ 15:30 β
β π
Appts β β 3 Critical β β’ Agent-11 β EMDR @ 16:00 β
β π Dash β β 5 Sessions β β
ββββββββββββββββ΄βββββββββββββββββββββββββββββββββββββββββββββββββββ
| Feature | Description |
|---|---|
| πΎ Agents | Create and manage AI agents with status tracking (active, recovering, discharged) |
| π€ Ailments | Log ailments with severity levels and timestamps |
| π Therapy Types | Define therapy sessions with custom duration, type, and metadata |
| π Appointments | Book agents into therapy slots with date, time, and therapist assignment |
| π Dashboard | Staff overview with real-time stats, filters, and upcoming appointment feed |
agenticclinic/
βββ app/ # Next.js 15 App Router
β βββ api/ # REST API endpoints (route handlers)
β β βββ agents/ # GET, POST /api/agents
β β βββ ailments/ # GET, POST /api/ailments
β β βββ therapy-types/ # GET, POST /api/therapy-types
β β βββ appointments/ # GET, POST /api/appointments
β βββ agents/ # Agent management UI
β β βββ page.tsx # Agent list
β β βββ [id]/page.tsx # Agent detail
β βββ ailments/ # Ailment tracking UI
β βββ therapy-types/ # Therapy management UI
β βββ appointments/ # Appointment booking UI
β βββ dashboard/ # Staff dashboard
β βββ layout.tsx # Root layout + nav
β βββ globals.css # Tailwind v4 base styles
β
βββ lib/
β βββ prisma.ts # Prisma singleton (prevents hot-reload leaks)
β
βββ prisma/
β βββ schema.prisma # Database schema (models + relations)
β βββ migrations/ # Auto-generated migration history
β
βββ specs/ # Spec-driven development documents
βββ phase-1-agents.md
βββ phase-2-therapy.md
βββ phase-3-dashboard.md
βββ phase-4-polish.md
βββββββββββββββββββββββββββββββ
β Browser (Client) β
β Next.js Client Components β
β (React, Tailwind v4, fetch) β
ββββββββββββββββ¬βββββββββββββββββ
β HTTP/HTTPS
ββββββββββββββββΌβββββββββββββββββ
β Next.js 15 App Router β
β βββββββββββββββββββββββββββ β
β β Server Components β β
β β (SSR, streaming) β β
β ββββββββββββ¬βββββββββββββββ β
β ββββββββββββΌβββββββββββββββ β
β β Route Handlers (API) β β
β β /api/* endpoints β β
β ββββββββββββ¬βββββββββββββββ β
βββββββββββββ-ββββββββββββββββββββ
β Prisma Client
βββββββββββββββΌβββββββββββββββββ
β Prisma ORM β
β Type-safe queries, migrationsβ
βββββββββββββββ¬βββββββββββββββββ
β
βββββββββββββββΌβββββββββββββββββ
β SQLite (local / Vercel) β
β agents, ailments, therapy, β
β appointments tables β
ββββββββββββββββββββββββββββββ-ββ
User Action β Client Component
β fetch('/api/resource', { method: 'POST', body })
β Route Handler (app/api/...)
β prisma.resource.create({ data: ... })
β SQLite write
β 200 OK + JSON
β Client re-render / revalidation
| App Router β | Pages Router | |
|---|---|---|
| Server Components | β Native | β None |
| Streaming & Suspense | β Built-in | |
| Nested Layouts | β Easy | |
| API co-location | β
route.ts next to page |
/pages/api/ |
| Bundle size | β Smaller (RSC) |
Tradeoff accepted: App Router has a steeper learning curve and some ecosystem libraries lag on support. Worth it for the streaming dashboard and reduced client-side JavaScript.
SQLite wins for this stage because:
- Zero configuration β no server process, no connection pooling
- Vercel-compatible via embedded file storage (for demo deploys)
- Prisma handles schema + migrations identically β swap the
DATABASE_URLand the code doesn't change
Tradeoffs accepted:
- No concurrent writes at scale (single writer lock)
- Not suitable for multi-region deployments
- File-based β doesn't work on stateless serverless with persistent storage needs
Scaling path: Switch
datasource dbinschema.prismafromsqlitetopostgresql, updateDATABASE_URL, runprisma migrate deploy. Application code changes: zero.
| Concern | Prisma |
|---|---|
| Type safety | β Auto-generated types from schema |
| Migration tracking | β
First-class migrate dev / migrate deploy |
| Schema as source of truth | β
Single schema.prisma file |
| Learning curve | β Gentle, great docs |
| Bundle size | |
| Edge runtime support |
Why not Drizzle? Drizzle is excellent and lighter β worth considering at scale. Prisma was chosen here for developer velocity and type-safety guarantees during spec-driven development where schema evolves rapidly.
The entire project was spec-first: requirements β validation criteria β code. This means:
- Every feature has a written contract before implementation
- Refactoring never breaks undocumented behaviour (because behaviour is documented)
- Onboarding new contributors is faster (read the spec, understand the intent)
See the /specs folder for all phase documents.
model Agent {
id Int @id @default(autoincrement())
name String
status String // "active" | "recovering" | "discharged"
createdAt DateTime @default(now())
ailments Ailment[]
appointments Appointment[]
}
model Ailment {
id Int @id @default(autoincrement())
agentId Int
agent Agent @relation(fields: [agentId], references: [id])
name String
severity String // "mild" | "moderate" | "severe" | "critical"
createdAt DateTime @default(now())
}
model TherapyType {
id Int @id @default(autoincrement())
name String // e.g. "CBT", "EMDR", "DBT"
durationMins Int
appointments Appointment[]
}
model Appointment {
id Int @id @default(autoincrement())
agentId Int
agent Agent @relation(fields: [agentId], references: [id])
therapyTypeId Int
therapyType TherapyType @relation(fields: [therapyTypeId], references: [id])
scheduledAt DateTime
createdAt DateTime @default(now())
}Key design decisions:
- Ailments are 1-to-many with Agent (an agent can have multiple ailments)
- Appointments join Agent β TherapyType (many-to-many resolved via Appointment)
- Severity and status use string enums (vs DB-level enums) for portability across SQLite β PostgreSQL
Single Vercel deployment
SQLite (file-based)
Monolithic Next.js app
No auth
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Auth Layer (NextAuth.js / Clerk) β
β Role-based: Staff vs Admin vs Read-only β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β PostgreSQL (Supabase / Railway / Neon) β
β Connection pooling via PgBouncer or Prisma Accelerate β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β API rate limiting (Upstash Redis) β
β Input validation (Zod schemas on all route handlers)β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Migration effort: 1β2 days. Prisma + Next.js abstractions mean the application layer barely changes.
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Multi-tenant schema (tenantId on all models) β
β Or: separate DB per clinic (schema-per-tenant pattern) β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Next.js deployed to Vercel Edge + Prisma Accelerate β
β Or: containerized (Docker) on Railway / Fly.io / ECS β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Background jobs (appointment reminders, report generation) β
β β Trigger.dev or Inngest for durable workflows β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Observability: Sentry (errors) + Axiom (logs) + Vercel Speed β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Read replicas for dashboard queries (analytics-heavy) β
β CQRS: separate read models for reporting β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Audit log table (all mutations tracked with actor + timestamp) β
β HIPAA-style compliance layer (for real medical contexts) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β REST β tRPC or GraphQL for typed client-server contracts β
β (tRPC is the natural next step given the TypeScript-first codebase) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
The architecture deliberately keeps the persistence layer behind a Prisma abstraction. This means:
- Switching from SQLite β PostgreSQL: change
DATABASE_URL, re-run migrations - Switching from Prisma β Drizzle: swap
lib/prisma.ts, update query syntax in API routes only - Switching from REST β tRPC: add
server/router.ts, generate types, update client fetches
The application's domain logic (agents, ailments, appointments) never directly touches the DB driver.
app/agents/page.tsx and app/api/agents/route.ts live near each other intentionally. When you're reading the agents feature, both the UI and the API contract are a single folder away. This reduces the "context switching cost" of full-stack development.
Because every feature started as a written spec (in /specs), refactors don't guess at intent. The spec defines the contract; the code fulfils it. Tests (when added) verify against the spec, not the implementation.
- Node.js 20+
- npm
git clone https://github.com/divyat2605/spec-driven-development.git
cd agenticclinic
npm installnpx prisma migrate dev --name init
npx prisma generatenpm run devPhase 1 ββββββββββββ Agents & Ailments foundation β
Done
Phase 2 ββββββββββββ Therapy types & Appointments β
Done
Phase 3 ββββββββββββ Dashboard & staff workflows β
Done
Phase 4 ββββββββββββ Polish, tests & deployment β
Done
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Phase 5 ββββββββββββ Auth + role-based access π Next
Phase 6 ββββββββββββ PostgreSQL + connection pooling π Planned
Phase 7 ββββββββββββ tRPC + end-to-end type safety π‘ Exploring
Phase 8 ββββββββββββ Multi-tenant & audit logging π‘ Exploring
- Fork the repo
- Create a feature branch:
git checkout -b feature/my-feature - Write a spec first in
/specsβ this project is spec-driven - Implement against the spec
- Open a PR referencing the spec document
MIT Β© divyat2605
Built with π€ for π€ β because even AI agents deserve good healthcare.
Made with Next.js Β· Prisma Β· SQLite Β· Tailwind CSS Β· Spec-Driven Development