# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

NoteAI is a local knowledge note-taking application built with Next.js, Prisma (SQLite), and TipTap editor. The app provides a hierarchical page structure with rich text editing, markdown import/export, and password-protected access.

## Development Commands

```bash
# Development server (runs on port 3001)
npm run dev

# Build for production
npm run build

# Initialize environment variables
npm run env:init

# Build with environment initialization
npm run build:init

# Start production server (port 3001)
npm start

# Linting
npm run lint

# Type checking and linting together
npm run check

# Run editor block operations tests
npm test
```

## Architecture

### Database Layer (Prisma + SQLite)

- **Schema**: `prisma/schema.prisma`
- **Client**: Singleton instance in `src/lib/prisma.ts`
- **Models**:
  - `Page`: Hierarchical pages with self-referential parent-child relationships. Supports both "file" and "folder" types with ordering, locking, tags, and icons.
  - `GlobalSettings`: Stores scrypt-hashed password for app-wide authentication.

### State Management

- **Zustand stores** with persistence:
  - `src/lib/store.ts`: Main editor state (pages, activePageId, CRUD operations)
  - `src/lib/search-store.ts`: Search functionality state
  - `src/lib/settings-store.ts`: Application settings state
  - `src/lib/page-history.ts`: Undo/redo history management with snapshots

### Authentication & Session

- **Session management**: `src/lib/session.ts` - Custom HMAC-based session tokens stored in cookies (24h TTL)
- **Auth utilities**: `src/lib/auth.ts` - Scrypt password hashing/verification
- **API auth**: `src/lib/api-auth.ts` - Middleware for protecting API routes
- **Rate limiting**: `src/lib/rate-limit.ts` - Token bucket rate limiter for auth endpoints

### Editor System (TipTap)

- **Extensions**: Custom TipTap extensions in `src/components/editor/extensions/`
  - `callout.ts` & `callout-component.tsx`: Custom callout blocks
  - `ai-mark.ts`: AI-generated content marking
  - `task-item.tsx`: Custom task list items
- **Block operations**: `src/lib/editor-block-ops.ts` - Core logic for moving/reordering contiguous spans of blocks (drag-and-drop support)
- **Tests**: `src/lib/editor-block-ops.test.ts` run via `scripts/run-editor-block-ops-tests.mjs`

**CRITICAL: Editor Initialization Configuration**

When modifying `src/components/editor.tsx`, preserve these critical settings for proper markdown import functionality:

```typescript
// In useEditor() configuration:
{
  extensions: [
    // ... other extensions
    Markdown.configure({
      html: true,
      transformPastedText: true,
      transformCopiedText: true,  // MUST be true for markdown conversion
    }),
  ],
  content,  // MUST pass content prop directly, NOT empty string
  onUpdate: ({ editor }) => {
    // ... update logic
  }
}

// In useEffect for content updates:
useEffect(() => {
  if (editor && content !== editor.getHTML()) {
    const normalizedContent = cleanupAccidentalStandaloneInlineCode(content);
    suppressNextUpdateRef.current = true;
    allowOnUpdateRef.current = false;
    queueMicrotask(() => {
      editor.commands.setContent(normalizedContent);  // Simple call, no extra options
    });
    if (normalizedContent !== content) {
      onChange(normalizedContent);
    }
  }
  if (editor && onEditorReady) {
    onEditorReady(editor);
  }
}, [content, editor, onEditorReady]);  // Dependencies: do NOT include onChange
```

**Common mistakes to avoid:**
- Setting `content: ''` instead of `content` breaks markdown import display
- Setting `transformCopiedText: false` disables markdown conversion
- Adding unnecessary options to `setContent()` can cause whitespace issues
- Including `onChange` in useEffect dependencies causes infinite re-renders

### Import/Export

- **Markdown import**: `src/lib/markdown-import.ts` - Converts markdown to HTML with special handling for fenced code blocks
- **Export**: `src/lib/export.ts` - Handles exporting pages to various formats
- **File I/O**: `src/lib/file-io.ts` - File system operations for import/export
- **HTML sanitization**: `src/lib/sanitize-html.ts` - Sanitizes HTML content

### API Routes

All routes in `src/app/api/`:
- `/api/auth/login` & `/api/auth/logout`: Authentication
- `/api/settings/init`: First-time password setup (requires `INIT_SETUP_TOKEN` in production)
- `/api/settings/password`: Change password
- `/api/settings/status`: Check initialization status
- `/api/settings/restore`: Restore from backup
- `/api/pages`: CRUD operations for pages
- `/api/pages/[id]`: Individual page operations
- `/api/pages/reorder`: Batch reorder pages
- `/api/ai/chat`: AI chat integration

### Special Features

- **Wiki links**: `src/lib/wiki-links.ts` - Internal page linking system
- **Page utilities**: `src/lib/page-utils.ts` - Helper functions for page operations
- **Search**: `src/lib/search-query.ts` - Search query parsing and execution

## Environment Variables

Required in `.env`:
```env
DATABASE_URL="file:./dev.db"
SESSION_SECRET="<32+ character random string>"
INIT_DEFAULT_PASSWORD="<initial password>"
INIT_SETUP_TOKEN="<optional token for production init>"
```

## Path Aliases

- `@/*` maps to `src/*` (configured in `tsconfig.json`)

## Testing

Tests use Node's native test runner with `--experimental-strip-types` flag. Test files use `.test.ts` extension and are run via custom scripts in `scripts/` directory.

## Database Migrations

```bash
# Generate Prisma client after schema changes
npx prisma generate

# Create and apply migrations
npx prisma migrate dev

# Apply migrations in production
npx prisma migrate deploy
```

## Build Targets

Prisma is configured for both native and `linux-musl-openssl-3.0.x` targets to support Docker deployments.
