# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview A lightweight web-based Markdown note-taking application with a Go backend and modern JavaScript frontend. Notes are stored as plain Markdown files with YAML front matter containing metadata (title, date, last_modified, tags). The system provides a sophisticated CodeMirror 6 editor with live preview, rich search capabilities, hierarchical organization, and automatic front matter management. **Key Features**: - **Daily Notes**: Quick daily journaling with interactive calendar, keyboard shortcuts (Ctrl/Cmd+D), and structured templates - **Favorites System**: Star important notes and folders for quick access from the sidebar - **Note Linking**: Create links between notes with `/link` command and fuzzy search modal - **Vim Mode**: Full Vim keybindings support (hjkl navigation, modes, commands) for power users - **Multiple Themes**: 8 dark themes (Material Dark, Monokai, Dracula, One Dark, Solarized, Nord, Catppuccin, Everforest) - **Font Customization**: 8 fonts (JetBrains Mono, Fira Code, Inter, etc.) with 4 size options - **Keyboard Shortcuts**: 10+ global shortcuts for navigation, editing, and productivity **Recent Modernization**: The project has been migrated from a simple textarea editor to CodeMirror 6, with a Vite build system for frontend modules. The backend remains unchanged, maintaining the same Go architecture with htmx for dynamic interactions. ## Architecture ### Backend (Go) Four main packages under `internal/`: - **indexer**: Maintains an in-memory index mapping tags to note files. Parses YAML front matter from `.md` files to build the index. Thread-safe with RWMutex. - **watcher**: Uses `fsnotify` to monitor filesystem changes and trigger re-indexing with 200ms debounce. Recursively watches all subdirectories. - **api**: HTTP handlers that serve templates and handle CRUD operations on notes. Updates front matter automatically on save. - `handler.go` - Main HTML endpoints for the web interface - `rest_handler.go` - REST API endpoints (v1) - `daily_notes.go` - Daily note creation and calendar functionality - `favorites.go` - Favorites management (star/unstar notes and folders) The server (`cmd/server/main.go`) coordinates these components: 1. Loads initial index from notes directory 2. Starts filesystem watcher for automatic re-indexing 3. Pre-parses HTML templates from `templates/` 4. Serves routes: - `/` (main page) - `/api/v1/notes` and `/api/v1/notes/*` (REST API - JSON responses) - `/api/search` (HTML search results) - `/api/notes/*` (HTML editor for notes) - `/api/tree` (HTML file tree) - `/api/folders/create` (Folder management) - `/api/files/move` (File/folder moving) - `/api/home` (Home page) - `/api/daily-notes/*` (Daily note creation and calendar) - `/api/favorites/*` (Favorites management) 5. Handles static files from `static/` directory ### Frontend The frontend uses a modern build system with Vite and CodeMirror 6: #### Architecture - **Build System**: Vite compiles frontend modules from `frontend/src/` to `static/dist/` - **Editor**: CodeMirror 6 with Markdown language support, One Dark theme, and syntax highlighting - **Templates**: `index.html`, `editor.html`, `file-tree.html`, `search-results.html`, `new-note-prompt.html` - **HTMX Integration**: Server returns HTML fragments that htmx swaps into the DOM - **Out-of-band swaps**: Update the file tree after saves/deletes without full page reload #### Frontend Source Structure ``` frontend/src/ ├── main.js # Entry point - imports all modules ├── editor.js # CodeMirror 6 editor implementation with slash commands ├── vim-mode-manager.js # Vim mode integration for CodeMirror ├── search.js # Search modal with Ctrl/Cmd+K keyboard shortcut ├── link-inserter.js # Note linking modal for /link command ├── file-tree.js # Drag-and-drop file organization ├── favorites.js # Favorites system (star/unstar functionality) ├── daily-notes.js # Daily notes creation and calendar widget ├── keyboard-shortcuts.js # Global keyboard shortcuts management ├── theme-manager.js # Theme switching and persistence ├── font-manager.js # Font selection and size management └── ui.js # Sidebar toggle functionality ``` #### CodeMirror 6 Editor Features - **Syntax Highlighting**: Full Markdown language support (`@codemirror/lang-markdown`) - **Theme**: One Dark theme (`@codemirror/theme-one-dark`) - VS Code-inspired dark theme - **Vim Mode**: Optional full Vim keybindings (`@replit/codemirror-vim`) with hjkl navigation, modes, and commands - **Live Preview**: Debounced updates (150ms) synchronized with editor scroll position - **Auto-Save**: Triggers after 2 seconds of inactivity - **Keyboard Shortcuts**: - `Ctrl/Cmd+S` for manual save - `Ctrl/Cmd+D` for daily notes - `Ctrl/Cmd+K` for search - `Ctrl/Cmd+B` for sidebar toggle - `Tab` for proper indentation - Full keyboard navigation (see docs/KEYBOARD_SHORTCUTS.md) - **View Modes**: Toggle between split view, editor-only, and preview-only - **Slash Commands**: Type `/` to open command palette for quick Markdown insertion - **Front Matter Handling**: Automatically strips YAML front matter in preview #### File Tree Features - **Folder Management**: Expand/collapse folders with visual indicators (📁/📂) - **Drag & Drop**: Move files between folders with visual feedback - **Folder Creation**: Modal-based creation supporting nested paths - **Safe Validation**: Prevents dangerous path operations - **Favorites**: Star notes and folders for quick access (★ icon in sidebar) #### Rendering Pipeline - **marked.js**: Markdown to HTML conversion - **DOMPurify**: HTML sanitization to prevent XSS attacks - **Highlight.js**: Syntax highlighting for code blocks in preview - **Custom Themes**: 8 dark themes in `static/theme.css` with CSS custom properties - Material Dark (default) - Monokai - Dracula - One Dark - Solarized Dark - Nord - Catppuccin - Everforest ### HTMX + JavaScript Coordination (Optimized Architecture) **Key Principle**: HTMX handles ALL server interactions and DOM updates. JavaScript handles UI enhancements (editor, drag-and-drop, animations). #### Architecture Flow ``` User Interaction → HTMX (AJAX) → Go Server (HTML) → HTMX (DOM update) → JS Events (enhancements) ``` #### Best Practices **1. Use `htmx.ajax()` for JavaScript-initiated requests:** ```javascript // ✅ Good: Let HTMX handle the request and DOM updates htmx.ajax('POST', '/api/files/move', { values: { source, destination }, swap: 'none' // Server uses hx-swap-oob }); // ❌ Bad: Manual fetch + DOM manipulation const response = await fetch('/api/files/move', {...}); const html = await response.text(); target.innerHTML = html; htmx.process(target); // This is now unnecessary ``` **2. Listen to HTMX events instead of DOM observers:** ```javascript // ✅ Good: React to HTMX swaps document.body.addEventListener('htmx:afterSwap', (event) => { if (event.detail.target.id === 'file-tree') { updateDraggableAttributes(); } }); document.body.addEventListener('htmx:oobAfterSwap', (event) => { if (event.detail.target.id === 'file-tree') { updateDraggableAttributes(); } }); // ❌ Bad: MutationObserver (performance overhead) const observer = new MutationObserver(() => {...}); observer.observe(element, { childList: true, subtree: true }); ``` **3. Let HTMX process out-of-band swaps automatically:** The server returns HTML with `hx-swap-oob` attributes. HTMX automatically finds these elements and swaps them, even when they're not the primary target. ```go // Server response (Go template)