# 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 <repository-url>
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 (
    <div>
      <h1>Hello from Memento!</h1>
    </div>
  )
}
```

**Usage:**
```tsx
import MyComponent from '@/components/my-component'

export default function Page() {
  return <MyComponent />
}
```

### 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 <div>{title}: {count}</div>
}
```

---

## Styling Guide

### Tailwind CSS Classes

**Documentation:** https://tailwindcss.com/docs

**Common Patterns:**
```tsx
// Spacing
<div className="p-4 m-2">      // Padding 4, margin 2
<div className="gap-4">       // Gap between children

// Colors
<div className="bg-blue-500 text-white">
<div className="text-gray-700 dark:text-gray-300">

// Typography
<h1 className="text-2xl font-bold">
<p className="text-sm leading-relaxed">

// Layout
<div className="flex flex-col md:flex-row">
<div className="grid grid-cols-3 gap-4">

// Responsive
<div className="hidden md:block">
<div className="w-full md:w-1/2">
```

### Custom CSS

**Global Styles:** `app/globals.css`

**Component-Specific:**
```tsx
// Use Tailwind @apply or inline styles
<div style={{ customProperty: 'value' }} />

// Or CSS modules
import styles from './MyComponent.module.css'
<div className={styles.container}>
```

---

## 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 <div>Welcome {session.user.name}</div>
}
```

**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'

<Image
  src="/image.png"
  alt="Description"
  width={500}
  height={300}
  priority // For above-fold images
/>
```

### 2. Code Splitting

```tsx
// Dynamic import for heavy components
import dynamic from 'next/dynamic'

const HeavyComponent = dynamic(() => import('./HeavyComponent'), {
  loading: () => <div>Loading...</div>,
  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 <div>{data}</div>
}
```

**Client Component:**
```tsx
'use client' // Required for interactivity

export default function InteractiveComponent() {
  const [count, setCount] = useState(0)
  return <button onClick={() => setCount(count + 1)}>{count}</button>
}
```

---

## 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.
