# 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="" INIT_SETUP_TOKEN="" ``` ## 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.