A full-stack AI-powered clinical notes application for therapists and mental health professionals. Write raw session notes, choose a structured format (SOAP / DAP / BIRP), and let GPT-4o generate polished clinical documentation in seconds. Includes Stripe billing with free / pro / team tiers.
- AI-assisted note generation (GPT-4o) in SOAP, DAP, and BIRP formats
- PDF export for every session note
- Stripe subscription billing (Free / Pro / Team) with usage metering
- Session-cookie authentication (httpOnly, secure in production)
- Rate-limited auth endpoints (5 req / 15 min) and global API limiter
- Helmet security headers with strict CSP in production
- PostgreSQL persistence via Drizzle ORM
| Layer | Technology |
|---|---|
| Frontend | React 18, TypeScript, Vite, Tailwind CSS, shadcn/ui |
| Backend | Node.js, Express, Passport.js (local strategy) |
| Database | PostgreSQL + Drizzle ORM, connect-pg-simple sessions |
| AI | OpenAI GPT-4o |
| Billing | Stripe (Checkout, Customer Portal, Webhooks) |
| DevOps | Docker, Docker Compose |
- Node.js 20+
- PostgreSQL 15+
- (Optional) Docker + Docker Compose
- OpenAI API key (for AI generation)
- Stripe account + keys (for billing features)
git clone https://github.com/biswajeetdev/Calm-Notes
cd Calm-Notes
cp .env.example .env
# Edit .env with your real values (see table below)| Variable | Required | Description |
|---|---|---|
DATABASE_URL |
Yes | PostgreSQL connection string, e.g. postgresql://user:pass@localhost:5432/calmnotes |
SESSION_SECRET |
Yes | Random string, min 32 chars — openssl rand -base64 48 |
OPENAI_API_KEY |
No | GPT-4o key — AI generation disabled if absent |
STRIPE_SECRET_KEY |
No | Stripe secret key (sk_test_...) — billing disabled if absent |
STRIPE_WEBHOOK_SECRET |
No | Webhook signing secret (whsec_...) |
STRIPE_PRICE_ID_PRO |
No | Stripe Price ID for the Pro plan |
STRIPE_PRICE_ID_TEAM |
No | Stripe Price ID for the Team plan |
NODE_ENV |
No | development (default) or production |
PORT |
No | Server port (default: 5000) |
npm install # installs root + workspace deps
npm run db:push # apply Drizzle schema to your DB
npm run dev # starts Express + Vite dev server on :5000# Make sure .env is filled in, then:
docker compose up --buildThe app will be available at http://localhost:5000.
Calm-Notes/
├── client/ # React + Vite frontend
│ └── src/
│ ├── pages/ # Landing, Dashboard, NewNote, NoteDetail, Settings, Pricing
│ ├── hooks/ # useAuth, useNotes, useSubscription
│ └── lib/ # queryClient, api helpers
├── server/ # Express backend
│ ├── auth/ # Passport.js session auth + rate limiting
│ ├── billing/ # Stripe checkout, portal, webhooks
│ ├── routes.ts # Notes CRUD + AI generation + PDF export
│ ├── storage.ts # Drizzle data-access layer
│ └── db.ts # PostgreSQL pool
└── shared/ # Types and schema shared between client and server
- Passwords hashed with bcrypt (10 rounds)
- Session cookie:
httpOnly: true,secure: truein production,sameSite: lax - Helmet CSP enabled in production
- Auth endpoints rate-limited: 5 req / 15 min per IP
- Stripe webhook signatures verified before processing
passwordHashfield stripped from all API responses