# Development Guide - keep-notes (Memento Web App) ## Overview Complete development guide for the Memento web application. Covers setup, development workflow, debugging, testing, and common tasks. --- ## Prerequisites ### Required Software | Tool | Version | Purpose | |------|---------|---------| | **Node.js** | 20+ | JavaScript runtime | | **npm** | Latest | Package manager | | **Git** | Latest | Version control | ### Recommended Tools | Tool | Purpose | |------|---------| | VS Code | IDE with great TypeScript/React support | | Prisma Studio | Database GUI for viewing/editing data | | Postman/Insomnia | API testing | | Playwright VS Code | E2E test debugging | --- ## Initial Setup ### 1. Clone Repository ```bash git clone cd Keep ``` ### 2. Install Dependencies ```bash cd keep-notes npm install ``` **Expected packages:** - React 19.2.3 - Next.js 16.1.1 - Prisma 5.22.0 - 100+ dependencies ### 3. Database Setup ```bash # Generate Prisma client npm run db:generate # Run migrations (if needed) npx prisma migrate dev # Open Prisma Studio (optional) npx prisma studio ``` **Prisma Studio:** - Opens at http://localhost:5555 - View and edit database records - Visual database schema ### 4. Environment Configuration Create `.env` file in `keep-notes/`: ```bash # Database DATABASE_URL="file:./prisma/dev.db" # NextAuth NEXTAUTH_SECRET="your-secret-key-here" NEXTAUTH_URL="http://localhost:3000" # Email (optional - for password reset) SMTP_HOST="smtp.example.com" SMTP_PORT="587" SMTP_USER="your-email@example.com" SMTP_PASS="your-password" SMTP_FROM="noreply@memento.app" # AI Providers (optional) OPENAI_API_KEY="sk-..." OLLAMA_API_URL="http://localhost:11434" ``` **Generate NEXTAUTH_SECRET:** ```bash openssl rand -base64 32 ``` --- ## Development Workflow ### Start Development Server ```bash npm run dev ``` **Server starts at:** http://localhost:3000 **Features:** - Hot reload (Fast Refresh) - TypeScript checking - Source maps for debugging - API routes available ### File Watching Next.js automatically watches for changes in: - `app/` directory - `components/` directory - `lib/` directory - `public/` directory **Automatic Actions:** - Recompile changed files - Refresh browser (HMR) - Regenerate Prisma client if schema changes --- ## Common Development Tasks ### 1. Create a New Component ```bash # Create component file touch components/my-component.tsx ``` ```typescript // components/my-component.tsx export default function MyComponent() { return (

Hello from Memento!

) } ``` **Usage:** ```tsx import MyComponent from '@/components/my-component' export default function Page() { return } ``` ### 2. Add a New API Route ```bash # Create API route directory mkdir -p app/api/my-resource touch app/api/my-resource/route.ts ``` ```typescript // app/api/my-resource/route.ts import { NextResponse } from 'next/server' export async function GET() { return NextResponse.json({ message: 'Hello' }) } export async function POST(request: Request) { const body = await request.json() return NextResponse.json({ received: body }) } ``` **Access:** http://localhost:3000/api/my-resource ### 3. Add a New Server Action ```bash # Create action file touch app/actions/my-action.ts ``` ```typescript 'use server' import { prisma } from '@/lib/prisma' import { revalidatePath } from 'next/cache' export async function myAction(id: string) { const result = await prisma.note.update({ where: { id }, data: { /* updates */ } }) revalidatePath('/') return result } ``` **Usage in Component:** ```tsx import { myAction } from '@/app/actions/my-action' export default function MyComponent() { async function handleSubmit() { await myAction('note-id') } } ``` ### 4. Modify Database Schema ```bash # 1. Edit schema nano prisma/schema.prisma # 2. Create migration npx prisma migrate dev --name my_changes # 3. Update client npm run db:generate ``` **Example Schema Change:** ```prisma model Note { // ... existing fields newField String? // Add new optional field } ``` ### 5. Run Tests ```bash # Run all E2E tests npm test # Run tests with UI npm run test:ui # Run tests in headed mode (see browser) npm run test:headed ``` **Test Reports:** - HTML: `playwright-report/index.html` - Results: `test-results/.last-run.json` --- ## Database Operations ### View Data with Prisma Studio ```bash npx prisma studio # Opens at http://localhost:5555 ``` **Features:** - Browse tables - Edit records - Add records - Filter and query ### Manual Database Queries ```bash # Open SQLite CLI sqlite3 keep-notes/prisma/dev.db # Query notes SELECT * FROM Note LIMIT 10; # Query users SELECT * FROM User; # Exit .quit ``` ### Reset Database ```bash # Delete database file rm keep-notes/prisma/dev.db # Re-run migrations npx prisma migrate dev # Seed data (if you have a seed script) npx prisma db seed ``` --- ## Debugging ### Server-Side Debugging **VS Code Launch Config:** Create `.vscode/launch.json`: ```json { "version": "0.2.0", "configurations": [ { "name": "Next.js: debug server-side", "type": "node-terminal", "request": "launch", "command": "npm run dev" }, { "name": "Next.js: debug client-side", "type": "chrome", "request": "launch", "url": "http://localhost:3000" } ] } ``` ### Console Logging **Server Components:** ```typescript console.log('Server log', data) // Appears in terminal ``` **Client Components:** ```typescript console.log('Client log', data) // Appears in browser console ``` ### Debug API Routes Add logging to API routes: ```typescript export async function GET(request: NextRequest) { console.log('GET /api/notes called') console.log('Query params:', request.nextUrl.searchParams) const notes = await prisma.note.findMany() console.log('Found notes:', notes.length) return NextResponse.json({ data: notes }) } ``` --- ## TypeScript Configuration ### Type Checking ```bash # Type check all files npx tsc --noEmit # Type check with watch mode npx tsc --noEmit --watch ``` ### Common Type Issues **1. Prisma Client Types:** ```typescript import prisma from '@/lib/prisma' // Use Prisma types type Note = Prisma.NoteGetPayload<{ include: {} }> ``` **2. Server Actions:** ```typescript 'use server' // Server actions must be async export async function myAction() { // Action logic } ``` **3. Component Props:** ```typescript interface MyComponentProps { title: string count?: number // Optional } export default function MyComponent({ title, count = 0 }: MyComponentProps) { return
{title}: {count}
} ``` --- ## Styling Guide ### Tailwind CSS Classes **Documentation:** https://tailwindcss.com/docs **Common Patterns:** ```tsx // Spacing
// Padding 4, margin 2
// Gap between children // Colors
// Typography

// Layout

// Responsive
``` ### Custom CSS **Global Styles:** `app/globals.css` **Component-Specific:** ```tsx // Use Tailwind @apply or inline styles
// Or CSS modules import styles from './MyComponent.module.css'
``` --- ## Working with Prisma ### Common Queries **Find all notes for a user:** ```typescript const notes = await prisma.note.findMany({ where: { userId: session.user.id }, orderBy: { updatedAt: 'desc' } }) ``` **Create a note:** ```typescript const note = await prisma.note.create({ data: { title: 'My Note', content: 'Note content', color: 'blue', userId: session.user.id } }) ``` **Update a note:** ```typescript const note = await prisma.note.update({ where: { id: noteId }, data: { title: 'Updated Title', content: 'Updated content' } }) ``` **Delete a note:** ```typescript await prisma.note.delete({ where: { id: noteId } }) ``` **Search notes:** ```typescript const notes = await prisma.note.findMany({ where: { OR: [ { title: { contains: query, mode: 'insensitive' } }, { content: { contains: query, mode: 'insensitive' } } ] } }) ``` ### Transaction Support ```typescript await prisma.$transaction(async (tx) => { // Multiple operations await tx.note.create({ data: note1 }) await tx.note.create({ data: note2 }) }) ``` --- ## Authentication Development ### NextAuth Configuration **Config File:** `auth.config.ts` **Add OAuth Provider:** ```typescript export const { handlers, signIn, signOut, auth } = NextAuth({ providers: [ Google({ clientId: process.env.GOOGLE_CLIENT_ID, clientSecret: process.env.GOOGLE_CLIENT_SECRET, }), // ... other providers ], }) ``` ### Protected Routes **Server Component:** ```tsx import { auth } from '@/auth' import { redirect } from 'next/navigation' export default async function ProtectedPage() { const session = await auth() if (!session) { redirect('/login') } return
Welcome {session.user.name}
} ``` **API Route:** ```typescript import { auth } from '@/auth' export async function GET() { const session = await auth() if (!session?.user) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) } return NextResponse.json({ data: 'secret' }) } ``` --- ## AI Integration Development ### Add New AI Provider **1. Create Provider File:** ```bash touch lib/ai/providers/my-provider.ts ``` **2. Implement Provider:** ```typescript // lib/ai/providers/my-provider.ts export function createMyProvider() { return { generateText: async (prompt) => { // Call AI API return response } } } ``` **3. Register in Factory:** ```typescript // lib/ai/factory.ts export function getProvider(provider: string) { switch (provider) { case 'my-provider': return createMyProvider() // ... existing providers } } ``` ### Use AI SDK ```typescript import { generateText } from 'ai' import { openai } from '@ai-sdk/openai' const response = await generateText({ model: openai('gpt-4'), prompt: 'Generate tags for this note...', }) console.log(response.text) ``` --- ## Performance Optimization ### 1. Image Optimization ```tsx import Image from 'next/image' Description ``` ### 2. Code Splitting ```tsx // Dynamic import for heavy components import dynamic from 'next/dynamic' const HeavyComponent = dynamic(() => import('./HeavyComponent'), { loading: () =>
Loading...
, ssr: false // Client-only }) ``` ### 3. Server Components (Default) ```tsx // Server components are default (no 'use client') export default async function Page() { const data = await fetch('https://api.example.com/data') return
{data}
} ``` **Client Component:** ```tsx 'use client' // Required for interactivity export default function InteractiveComponent() { const [count, setCount] = useState(0) return } ``` --- ## Testing Guide ### Write E2E Test **File:** `tests/my-feature.spec.ts` ```typescript import { test, expect } from '@playwright/test' test('my feature test', async ({ page }) => { await page.goto('http://localhost:3000') await page.fill('input[name="email"]', 'test@example.com') await page.click('button[type="submit"]') await expect(page).toHaveURL('/dashboard') }) ``` ### Run Specific Test ```bash npx playwright test tests/my-feature.spec.ts ``` ### Debug Tests ```bash # Run with UI npm run test:ui # Run headed mode npm run test:headed # Debug mode npx playwright test --debug ``` --- ## Common Issues & Solutions ### Issue: Prisma Client Not Generated **Solution:** ```bash npm run db:generate ``` ### Issue: Port Already in Use **Solution:** ```bash # Kill process on port 3000 npx kill-port 3000 # Or find and kill manually lsof -ti:3000 | xargs kill -9 ``` ### Issue: Module Not Found **Solution:** ```bash # Clear cache and reinstall rm -rf node_modules .next npm install ``` ### Issue: Database Locked **Solution:** ```bash # Close Prisma Studio or other DB connections # Or wait for SQLite to release lock ``` --- ## Build & Production ### Build for Production ```bash npm run build ``` **Output:** `.next/` directory ### Start Production Server ```bash npm start # Runs on port 3000 (or PORT env var) ``` ### Environment Variables for Production ```bash # .env.production DATABASE_URL="file:./prisma/dev.db" NEXTAUTH_SECRET="production-secret" NEXTAUTH_URL="https://your-domain.com" ``` --- ## Development Tips ### 1. Use TypeScript Strict Mode Already enabled in `tsconfig.json`: ```json { "compilerOptions": { "strict": true } } ``` ### 2. ESLint & Prettier ```bash # Lint code npm run lint # Fix linting issues npm run lint -- --fix ``` ### 3. Git Hooks (Optional) Install husky for pre-commit hooks: ```bash npm install -D husky lint-staged npx husky install ``` ### 4. VS Code Extensions Recommended: - Prisma - ESLint - Prettier - Tailwind CSS IntelliSense - TypeScript Vue Plugin (Volar) --- ## Resources ### Documentation - Next.js: https://nextjs.org/docs - Prisma: https://www.prisma.io/docs - React: https://react.dev - Tailwind CSS: https://tailwindcss.com/docs - Radix UI: https://www.radix-ui.com/primitives ### Community - Next.js GitHub Discussions - Prisma Slack - Stack Overflow ### Project-Specific - API Contracts: `docs/api-contracts-keep-notes.md` - Data Models: `docs/data-models.md` - Component Inventory: `docs/component-inventory.md` --- ## Summary The Memento web application uses a modern Next.js 16 stack with: - **App Router** for routing - **Server Components** by default - **Prisma ORM** for database access - **NextAuth** for authentication - **Tailwind CSS** for styling - **Playwright** for E2E testing This guide provides everything needed for local development, debugging, and testing.