主要改动: - API: 为 /api/pages 添加 lightweight 模式和分页支持 - 备份恢复: 增强 restore API 的错误处理和验证逻辑 - 工具函数: 新增 page-utils 辅助函数 - 会话管理: 优化 session 和 auth 相关逻辑 - 文档: 添加 CLAUDE.md 项目指南,包含编辑器配置注意事项 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
5.8 KiB
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
# 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 statesrc/lib/settings-store.ts: Application settings statesrc/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 blocksai-mark.ts: AI-generated content markingtask-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.tsrun viascripts/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:
// 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 ofcontentbreaks markdown import display - Setting
transformCopiedText: falsedisables markdown conversion - Adding unnecessary options to
setContent()can cause whitespace issues - Including
onChangein 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 (requiresINIT_SETUP_TOKENin 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:
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 tosrc/*(configured intsconfig.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
# 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.