tia/CLAUDE.md
Mannu 3e66b259f2 Migrate medical data from localStorage to database
- Add database tables: medicines, allergies, doctor_visits, illness_logs
- Create API endpoints: /api/medicines, /api/allergies, /api/visits, /api/illnesses
- Update medical page to use database APIs instead of localStorage
- All medical data now persists across sessions and devices

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-10 21:07:26 +05:30

192 lines
No EOL
6.6 KiB
Markdown

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Commands
```bash
# Development
pnpm dev # Start dev server at http://localhost:3000
pnpm build # Production build
pnpm start # Start production server
# Database (drizzle)
pnpm db:push # Push schema to database
pnpm db:generate # Generate drizzle types
pnpm db:studio # Open DB studio (or use direct SQL)
# Docker
docker-compose -f docker-compose.dev.yml up -d # Start local Postgres
```
**Note:** Running from `/Users/manohar_air/MyProjects/Tia/tia` directory.
## Architecture
### Tech Stack
- **Framework:** Next.js 16 with App Router (src/app/)
- **Database:** PostgreSQL 16 with pgvector + Drizzle ORM
- **Auth:** NextAuth v5 (beta) with magic links
- **AI:** LiteLLM gateway → MiniMax model (minimax-2.7)
- **Storage:** Cloudflare R2 for media uploads
- **Styling:** Tailwind CSS v4
### Project Structure
```
src/
├── app/ # Next.js App Router pages
│ ├── api/ # API routes (auth, logs, ai, growth, etc.)
│ ├── page.tsx # Home (Quick Log + AI card)
│ ├── ai/ # AI chat page with sidebar
│ ├── medical/ # Vaccination tracking
│ ├── growth/ # Growth charts
│ ├── memories/ # Photo gallery
│ ├── menu/ # Navigation menu
│ ├── onboarding/ # First-time setup
│ ├── settings/ # Settings with theme picker
│ └── login/ # Magic link login
├── ThemeProvider.tsx # Theme context (light/dark/system/time)
├── ThemeProvider
drizzle/ # Database migrations
docs/ # Design docs
```
### Database
- **Migrations:** SQL files in `drizzle/` (not using drizzle-kit push)
- **Apply:** `psql` directly or via docker-compose exec
- **RLS:** Row-level security for multi-family isolation
### Data Models
- **Family:** Parent account container
- **Members:** Adults in family (mom, dad, etc.)
- **Children:** Baby profiles with birth date
- **Logs:** Feed, sleep, diaper entries with timestamps
- **Vaccinations:** IAP schedule tracking
- **Growth:** Weight/height over time
- **Memories:** Photos with R2 storage
### Key Patterns
**ThemeProvider:** Wrap app in ThemeProvider from layout.tsx. Use `useTheme()` hook in components.
```typescript
import { useTheme } from "./ThemeProvider";
const { theme, toggle, setMode } = useTheme();
// theme: "light" | "dark"
// mode: "light" | "dark" | "system" | "time"
```
**Offline Queue:** Uses localStorage (`tia_offline_queue`) for failed API calls, retries when online.
**Chat Sessions:** Stored in localStorage (`tia_chat_sessions`) - shared between home page AI card and /ai page.
**API Routes:** Return standard JSON `{ success: true, items: [...] }` format for lists.
**AI Integration:**
- Route: `/api/ai` → LiteLLM at `https://llm.manohargupta.com`
- Model: `minimax-2.7`
- See `/docs/debugging.md` for troubleshooting
## Data Storage Consistency
### RULE: All user data must persist to database, NOT localStorage
| Data Type | Storage | API Key | Persists After Refresh | Persists After Logout |
|----------|---------|--------|------------------------|-------------------|
| Children | Database | `/api/children` | ✅ Yes | ✅ Yes |
| Activity Logs | Database | `/api/logs` | ✅ Yes | ✅ Yes |
| Vaccinations | Database | `/api/vaccinations` | ✅ Yes | ✅ Yes |
| Growth Records | Database | `/api/growth` | ✅ Yes | ✅ Yes |
| User Profile | Database | `/api/auth/profile` | ✅ Yes | ✅ Yes |
| Memories/Photos | Database + R2 | `/api/upload` | ✅ Yes | ✅ Yes |
| **Medicines** | Database | `/api/medicines` | ⚠️ TODO | ⚠️ TODO |
| **Allergies** | Database | `/api/allergies` | ⚠️ TODO | ⚠️ TODO |
| **Doctor Visits** | Database | `/api/visits` | ⚠️ TODO | ⚠️ TODO |
| **Illness Log** | Database | `/api/illnesses` | ⚠️ TODO | ⚠️ TODO |
| Theme | localStorage | `tia_theme` | ✅ Yes | ✅ Yes |
| Chat Sessions | localStorage | `tia_chat_sessions` | ✅ Yes | ❌ No |
| Offline Queue | localStorage | `tia_offline_queue` | ✅ Yes | ❌ No |
### localStorage acceptable for:
- Theme preference (user-specific display only)
- Temporary cache (offline queue for retry)
- Chat sessions (upcoming feature: move to database)
### NEVER use localStorage for:
- Medical/health data (medicines, allergies, visits, illnesses)
- Any data that should persist across devices
- Data important for pediatrician visits
### Audit (2026-05-10)
Current status - needs migration to database:
- `tia_medicines``/api/medicines`
- `tia_allergies``/api/allergies`
- `tia_visits``/api/visits`
- `tia_illnesses``/api/illnesses`
## R2 Storage (Cloudflare)
### Setup
1. **Create bucket** in Cloudflare Dashboard → R2
2. **Create API token** with "Object Read & Write" permissions
3. **Enable Public Development URL** in bucket settings (gives pub-*.r2.dev URL)
### API Endpoint Format
The S3 API endpoint is: `https://<accountId>.r2.cloudflarestorage.com`
For your bucket named "tia":
- Account ID: `e71f22a2f8614fb3ba6d9b28a264d8ce`
- S3 Endpoint: `https://e71f22a2f8614fb3ba6d9b28a264d8ce.r2.cloudflarestorage.com`
- Public URL: `https://pub-37a76fd657c94d1dbc521a109c087a11.r2.dev` (no bucket name in path!)
### Code Example
```typescript
const client = new S3Client({
region: "auto",
endpoint: `https://${accountId}.r2.cloudflarestorage.com`,
credentials: { accessKeyId, secretAccessKey },
});
// List objects
const command = new ListObjectsV2Command({ Bucket: "tia" });
const res = await client.send(command);
// Get presigned upload URL
const command = new PutObjectCommand({ Bucket: "tia", Key: key, ContentType });
const url = await getSignedUrl(client, command, { expiresIn: 3600 });
```
### Key Learnings
1. **S3 API endpoint** does NOT include bucket name: `https://...r2.cloudflarestorage.com`
2. **Public URL** does NOT include bucket path: `https://pub-...r2.dev` (NOT `/tia/...`)
3. **CORS** needs GET and PUT methods for uploads
4. ListObjects needs bucket name in command, not endpoint
## Environment Variables
Set in `.env.local` for development, or in Dokploy dashboard for production.
Required:
- `DATABASE_URL` - PostgreSQL connection
- `AUTH_SECRET` - NextAuth secret
- `R2_ACCOUNT_ID` - Cloudflare R2 account ID
- `R2_ACCESS_KEY_ID` - R2 access key
- `R2_SECRET_ACCESS_KEY` - R2 secret key
- `R2_BUCKET_NAME` - R2 bucket name (e.g., "tia")
- `R2_PUBLIC_URL` - Public R2 URL (e.g., `https://pub-...r2.dev`)
Optional for AI:
- `LITELLM_BASE_URL` - AI gateway URL
- `LITELLM_API_KEY` - AI API key