diff --git a/CLAUDE.md b/CLAUDE.md index 1008a2a..2e970df 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -9,23 +9,71 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Common Commands ```bash +# Development pnpm dev # Start local dev server -pnpm build # Production build -pnpm start # Start production server +pnpm build # Production build +npm ci # Clean install for Docker + +# Database (Drizzle) +npx drizzle-kit generate # Generate migration from schema +npx drizzle-kit push # Push schema to DB ``` ## Environment Variables -See `.env.example` for required variables including DATABASE_URL, AUTH_SECRET, R2 credentials, LiteLLM config. +Required in `.env.local`: + +```env +DATABASE_URL=postgresql://tia:tia_local_dev@localhost:5433/tia_dev +AUTH_SECRET= +AUTH_URL=http://localhost:3000 +RESEND_API_KEY= +``` + +## Hits & Learned Lessons + +### Build Issues Fixed +1. **pnpm 11 + Node 20 incompatibility**: pnpm 11 requires Node 22+. Fixed by using Node 22 in Dockerfile. +2. **pnpm ignored builds in Docker**: Had to switch from pnpm to npm in Dockerfile (`npm ci` instead of `pnpm install`). +3. **Drizzle adapter type errors**: Using simplified DrizzleAdapter without passing table configs directly fixes type errors. +4. **nodemailer missing**: NextAuth email provider requires nodemailer as a dependency. +5. **Middleware warning**: Next.js 16 shows deprecation warning for middleware file convention. + +### Database Setup +- Local: Docker Compose with pgvector on port 5433, Redis on 6380 +- Schema: 8 tables (users, accounts, sessions, verification_tokens, families, family_members, children, family_invites) +- Migrations: Run via `npx drizzle-kit push` or docker exec with SQL files + +### Docker Build +- Use `npm ci` instead of pnpm in Docker for reliability +- Node 22 alpine image +- Multi-stage build (deps → builder → runner) +- Need to install nodemailer separately for email auth + +## Architecture + +- **Framework**: Next.js 16 (App Router) with TypeScript +- **Database**: PostgreSQL 16 with pgvector (Drizzle ORM) +- **Auth**: NextAuth v5 beta +- **Deployment**: Dokploy (Docker) ## Sprint Plan -Current: Sprint 0 (Foundation Infrastructure) -- Sprint 0: Dev environment, Docker, Dokploy deploy -- Sprint 1: Auth + Database with RLS +Current: Sprint 1 (Database + Auth) + +- Sprint 0: Dev environment, Docker, Dokploy deploy ✅ +- Sprint 1: Auth + Database with RLS (in progress) - Sprint 2: Fast-log engine - Sprint 3: Medical vault - Sprint 4: Media pipeline - Sprint 5: AI Brain - Sprint 6: UI/UX polish -- Sprint 7: Telegram alerts + launch \ No newline at end of file +- Sprint 7: Telegram alerts + launch + +## Key Files + +- `src/auth.ts` - NextAuth configuration +- `src/db/schema/auth.ts` - Auth tables (users, sessions, accounts) +- `src/db/schema/family.ts` - Family, members, children tables +- `src/app/login/page.tsx` - Login page +- `Dockerfile` - Production build (uses npm, not pnpm) \ No newline at end of file diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx index 06bd0a6..7f64608 100644 --- a/src/app/login/page.tsx +++ b/src/app/login/page.tsx @@ -5,15 +5,36 @@ import { useState } from "react"; export default function LoginPage() { const [email, setEmail] = useState(""); - const [loading, setLoading] = useState(false); + const [status, setStatus] = useState<"idle" | "loading" | "success" | "error">("idle"); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); - setLoading(true); - await signIn("email", { email }); - setLoading(false); + setStatus("loading"); + + const result = await signIn("email", { email, redirect: false }); + + if (result?.ok) { + setStatus("success"); + } else { + setStatus("error"); + setTimeout(() => setStatus("idle"), 3000); + } }; + if (status === "success") { + return ( +
+ We sent a magic link to {email} +
++ We sent you a magic link to sign in. +
++ Click the link in the email to sign in to Tia. +
+