34 KiB
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
/linkcommand 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
.mdfiles to build the index. Thread-safe with RWMutex. - watcher: Uses
fsnotifyto 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 interfacerest_handler.go- REST API endpoints (v1)daily_notes.go- Daily note creation and calendar functionalityfavorites.go- Favorites management (star/unstar notes and folders)
The server (cmd/server/main.go) coordinates these components:
- Loads initial index from notes directory
- Starts filesystem watcher for automatic re-indexing
- Pre-parses HTML templates from
templates/ - Serves routes:
/(main page)/api/v1/notesand/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)
- 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/tostatic/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+Sfor manual saveCtrl/Cmd+Dfor daily notesCtrl/Cmd+Kfor searchCtrl/Cmd+Bfor sidebar toggleTabfor 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.csswith 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:
// ✅ 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:
// ✅ 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.
// Server response (Go template)
<div id="file-tree" hx-swap-oob="innerHTML">
<!-- Updated file tree HTML -->
</div>
HTMX automatically:
- Finds the element with
id="file-tree" - Replaces its innerHTML
- Processes any HTMX attributes in the new content
- Triggers
htmx:oobAfterSwapevent
4. Event-driven architecture:
// File tree initialization (file-tree.js)
class FileTree {
constructor() {
this.init();
}
init() {
// Use event delegation on stable parent
const sidebar = document.getElementById('sidebar');
// Click handlers (delegated)
sidebar.addEventListener('click', (e) => {
const folderHeader = e.target.closest('.folder-header');
if (folderHeader) this.toggleFolder(folderHeader);
});
// Drag-and-drop handlers (delegated)
sidebar.addEventListener('dragstart', (e) => {...});
sidebar.addEventListener('drop', (e) => {...});
// React to HTMX updates
document.body.addEventListener('htmx:oobAfterSwap', (event) => {
if (event.detail.target.id === 'file-tree') {
this.updateDraggableAttributes();
}
});
}
}
Implementation Examples
Creating a folder (file-tree.js:438-476):
htmx.ajax('POST', '/api/folders/create', {
values: { path: folderName },
swap: 'none' // Server handles oob swap
}).then(() => {
hideNewFolderModal();
}).catch(() => {
alert('Erreur lors de la création du dossier');
});
Moving a file (file-tree.js:338-362):
htmx.ajax('POST', '/api/files/move', {
values: { source: sourcePath, destination: destinationPath },
swap: 'none' // Server handles oob swap
}).then(() => {
console.log('File moved successfully');
});
Benefits of This Architecture
- Less Code: ~60 lines removed by eliminating manual DOM manipulation
- Better Performance: HTMX events instead of MutationObserver
- Consistency: All server interactions use the same pattern
- Maintainability: Clear separation between HTMX (data) and JavaScript (UI enhancements)
- Reliability: HTMX handles edge cases (race conditions, partial updates, etc.)
When to Use What
Use HTMX for:
- Loading content from server
- Form submissions
- Search/filtering
- File operations (move, delete, create)
- Automatic DOM updates
Use JavaScript for:
- CodeMirror editor initialization
- Drag-and-drop UI logic
- Slash command palette
- Scroll synchronization
- View mode toggles
- Client-side animations
Never:
- Parse HTML manually from fetch() responses
- Call
htmx.process()manually (HTMX does it automatically) - Use MutationObserver when HTMX events are available
- Mix fetch() and htmx.ajax() for similar operations
Daily Notes
Implementation: internal/api/daily_notes.go and frontend/src/daily-notes.js
Daily notes provide a quick journaling feature:
- Keyboard Shortcut:
Ctrl/Cmd+Dcreates or opens today's note - Calendar Widget: Interactive monthly calendar showing all daily notes
- Template System: Uses
daily-note-template.mdif present in notes directory - Auto-naming: Creates notes as
daily/YYYY-MM-DD.mdby default - Visual Indicators: Calendar highlights days with existing notes
- One-click Access: Click any calendar date to open or create that day's note
The calendar is implemented using htmx for dynamic month navigation and rendering.
Favorites System
Implementation: internal/api/favorites.go and frontend/src/favorites.js
The favorites system allows quick access to frequently used notes and folders:
- Star Icon: Click ★ next to any note or folder in the file tree
- Persistence: Favorites stored in
.favorites.jsonin the notes directory - Quick Access: Starred items appear at the top of the sidebar
- Folder Support: Star entire folders to quickly access project areas
- Visual Feedback: Filled star (★) for favorites, empty star (☆) for non-favorites
Favorites are loaded on server startup and updated in real-time via htmx.
Note Format
Notes have YAML front matter with these fields:
---
title: "Note Title"
date: "08-11-2025"
last_modified: "08-11-2025:13:02"
tags: [tag1, tag2]
---
The indexer package handles both single-value and array-format tags via custom UnmarshalYAML.
Development Commands
Building the Frontend
IMPORTANT: The frontend must be built before running the application. The compiled JavaScript is required.
cd frontend
npm install # Install dependencies (first time only)
npm run build # Compile frontend modules to static/dist/
Output files (loaded by templates):
static/dist/project-notes-frontend.es.js(ES module)static/dist/project-notes-frontend.umd.js(UMD format)
Frontend dependencies (from frontend/package.json):
@codemirror/basic-setup(^0.20.0) - Base editor functionality@codemirror/lang-markdown(^6.5.0) - Markdown language support@codemirror/state(^6.5.2) - Editor state management@codemirror/view(^6.38.6) - Editor view layer@codemirror/theme-one-dark(^6.1.3) - Dark theme@replit/codemirror-vim(^6.2.2) - Vim mode integrationvite(^7.2.2) - Build tool
Running the Server
go run ./cmd/server
Server starts on http://localhost:8080. Use flags to customize:
-addr :PORT- Change server address (default::8080)-notes-dir PATH- Change notes directory (default:./notes)
Testing
Run all tests:
go test ./...
Run specific package tests:
go test ./internal/indexer
go test ./internal/api
Run tests with verbose output:
go test -v ./...
Building the Server Binary
go build ./cmd/server
Backend Dependencies
Update Go dependencies:
go mod tidy
Key backend dependencies:
github.com/fsnotify/fsnotify- Filesystem watchergopkg.in/yaml.v3- YAML parsing for front matter
Vite Build System
The frontend uses Vite (frontend/vite.config.js) for bundling JavaScript modules:
Configuration:
- Entry Point:
frontend/src/main.js(imports editor.js, file-tree.js, ui.js) - Output Directory:
static/dist/(served by Go server) - Library Mode: Builds as a library with both ES and UMD formats
- Single Bundle: No code splitting - all dependencies bundled together
- Aliases: Path aliases for
@codemirror/stateand@codemirror/viewto ensure consistent versions
Build Process:
- Vite reads all source files from
frontend/src/ - Resolves npm dependencies (@codemirror packages)
- Bundles everything into two formats:
- ES module (
project-notes-frontend.es.js) - 1.0 MB - UMD (
project-notes-frontend.umd.js) - 679 KB
- ES module (
- Outputs to
static/dist/where Go server can serve them - Templates load the ES module version via
<script type="module">
Development Workflow:
cd frontend
npm run build # Build for production
npm run build -- --watch # Watch mode for development
The Go server does not need to be restarted after frontend builds - simply refresh the browser.
Key Implementation Details
Front Matter Management
The system automatically manages front matter when saving notes:
title: Auto-generated from filename if missing (converts hyphens to spaces, title-cases)date: Set to creation date for new files, preserved for existing fileslast_modified: Always updated to current timestamp on save (format:DD-MM-YYYY:HH:MM)tags: Preserved from user input; defaults to["default"]for new notes
Front matter extraction happens in two places:
indexer.ExtractFrontMatterAndBody()- For file pathsindexer.ExtractFrontMatterAndBodyFromReader()- Forio.Reader(used when parsing form content)
Indexing and Search
The indexer maintains two data structures:
tags map[string][]string- Maps tags to file paths for tag-based lookupdocs map[string]*Document- Stores full document metadata for rich search
Re-indexing happens:
- On server startup
- When files are created/modified/deleted (via watcher with 200ms debounce)
- After POST/DELETE/MOVE operations (background goroutine)
Rich search supports multiple query formats:
- General terms: Search across title, tags, path, and body (AND logic)
tag:value- Filter by specific tag (case-insensitive)title:value- Filter by title contentpath:value- Filter by file path- Quoted phrases:
"exact phrase"preserves spaces - Results are scored and ranked by relevance (title matches score highest)
REST API (v1)
The application includes a full REST API for programmatic access:
Implementation: internal/api/rest_handler.go
Endpoints:
GET /api/v1/notes- List all notes with metadata (JSON)GET /api/v1/notes/{path}- Get a specific note (JSON or Markdown based on Accept header)PUT /api/v1/notes/{path}- Create or update a note (accepts JSON or raw Markdown)DELETE /api/v1/notes/{path}- Delete a note
Content Negotiation:
Accept: application/json→ Returns JSON with full metadataAccept: text/markdown→ Returns raw Markdown contentContent-Type: application/json→ Accepts structured JSON requestContent-Type: text/markdown→ Accepts raw Markdown body
Key Features:
- Automatic front matter generation for new notes
- Front matter update (last_modified) on PUT operations
- Background re-indexing after modifications
- Path validation (same security as HTML endpoints)
- Supports nested folders (creates parent directories automatically)
Documentation: See API.md for full REST API documentation with examples.
Search Modal
A modern command-palette style search modal is available:
Implementation: frontend/src/search.js
Features:
- Keyboard shortcut:
Ctrl/Cmd+Kto open anywhere - Real-time search with 300ms debounce
- Keyboard navigation:
↑/↓to navigate,Enterto open,Escto close - Highlighting of search terms in results
- Uses existing search API (
/api/search) - Displays results with icons, titles, paths, snippets, tags, and dates
Styling: Custom styles in static/theme.css with Material Darker theme integration.
Theme and Font Customization
Implementation: frontend/src/theme-manager.js and frontend/src/font-manager.js
The application supports extensive UI customization:
Themes
8 dark themes available via Settings (⚙️ icon):
- Material Dark (default) - Material Design inspired
- Monokai - Classic Monokai colors
- Dracula - Popular purple-tinted theme
- One Dark - Atom/VS Code inspired
- Solarized Dark - Precision colors by Ethan Schoonover
- Nord - Arctic, north-bluish color palette
- Catppuccin - Soothing pastel theme
- Everforest - Comfortable greenish theme
Themes are applied via CSS custom properties and persist in localStorage.
Fonts
8 font options with 4 size presets (small, medium, large, extra-large):
- JetBrains Mono (default)
- Fira Code
- Inter
- IBM Plex Mono
- Source Code Pro
- Cascadia Code
- Roboto Mono
- Ubuntu Mono
Font settings apply to both the editor and preview pane.
Vim Mode
Implementation: frontend/src/vim-mode-manager.js using @replit/codemirror-vim
Optional Vim keybindings for power users:
- Enable/Disable: Toggle via Settings (⚙️ icon)
- Full Vim Support: hjkl navigation, visual mode, operators, text objects
- Mode Indicator: Shows current Vim mode (Normal/Insert/Visual) in editor
- Persistence: Vim mode preference saved to localStorage
- CodeMirror Integration: Native Vim extension with excellent compatibility
Vim mode users get full modal editing while maintaining CodeMirror features like syntax highlighting and auto-save.
Keyboard Shortcuts
Implementation: frontend/src/keyboard-shortcuts.js
The application provides 10+ global keyboard shortcuts for efficient navigation:
Essential Shortcuts:
Ctrl/Cmd+D- Create or open today's daily noteCtrl/Cmd+K- Open search modalCtrl/Cmd+S- Save current note (also triggers auto-save)Ctrl/Cmd+B- Toggle sidebar visibilityCtrl/Cmd+/- Show keyboard shortcuts help modal
Editor Shortcuts:
Tab- Indent (when in editor)Shift+Tab- Outdent (when in editor)Ctrl/Cmd+Enter- Save note (alternative to Cmd+S)
Navigation:
↑/↓- Navigate search results or command paletteEnter- Select/confirm actionEsc- Close modals, cancel actions, clear search
All shortcuts are non-blocking and work across the application. The shortcuts help modal (triggered by Ctrl/Cmd+/) provides a quick reference guide.
For complete documentation, see docs/KEYBOARD_SHORTCUTS.md.
Security Considerations
File path validation in handler.go and rest_handler.go:
filepath.Clean()to normalize paths- Reject paths starting with
..or absolute paths (directory traversal prevention) - Enforce
.mdextension for notes - Use
filepath.Join()to construct safe paths within notes directory - DOMPurify sanitizes Markdown-rendered HTML to prevent XSS attacks
REST API Security:
- No authentication currently implemented
- Recommend using reverse proxy (nginx, Caddy) with auth for public exposure
- CORS not configured (same-origin only)
- No rate limiting (add middleware if needed)
Template System
Templates are pre-parsed at startup. The API handler returns HTML fragments that htmx inserts into the page. Out-of-band swaps update the file tree sidebar without full page reload.
Concurrency
- Indexer uses
sync.RWMutexfor thread-safe access (read locks for searches, write locks for re-indexing) - Re-indexing after saves/deletes/moves happens in background goroutines to avoid blocking HTTP responses
- Watcher runs in separate goroutine with proper context cancellation
- Server shutdown uses 5-second graceful shutdown timeout with context
File Organization
The application supports hierarchical note organization:
- Notes can be organized in subdirectories within the
notes/directory - The file tree displays folders and files in a hierarchical view
- Folders are displayed before files, both sorted alphabetically (case-insensitive)
- API endpoints for folder creation (
/api/folders/create) and file moving (/api/files/move) - Watcher recursively monitors all subdirectories for changes
CodeMirror 6 Editor Implementation
The editor is implemented in frontend/src/editor.js with two main classes:
MarkdownEditor Class
Manages the CodeMirror 6 instance and its interactions:
Initialization:
EditorState.create({
doc: content,
extensions: [
basicSetup, // Line numbers, search, fold gutter
markdown(), // Markdown syntax support
oneDark, // One Dark theme
keymap.of([indentWithTab]),
EditorView.updateListener.of(...), // Preview & auto-save
keymap.of([{ key: "Mod-s", run: saveFunction }])
]
});
Key Features:
- Live Preview: Updates preview pane with 150ms debounce on editor changes
- Auto-Save: Triggers form submission after 2 seconds of inactivity
- Scroll Sync: Bidirectional scroll synchronization between editor and preview (50ms debounce)
- Front Matter Stripping: Removes YAML front matter from preview rendering
- View Modes: Three modes (split/editor-only/preview-only) saved to localStorage
- Height Management: Dynamic height calculation (
window.innerHeight - 180px) with resize handling - Cleanup: Proper destruction of editor instances to prevent memory leaks
Integration:
- Replaces the hidden textarea element
- HTMX events trigger editor initialization (
htmx:afterSwap) - Form submission uses
requestSubmit()to trigger HTMX POST
SlashCommands Class
Provides command palette for quick Markdown insertion:
Trigger: Type / at the beginning of a line to open the palette
Implementation:
- Monitors editor state changes for
/character - Filters commands in real-time as user types
- Positions palette dynamically using CodeMirror's
coordsAtPos() - Keyboard navigation with arrow keys, Enter/Tab to select
- Inserts Markdown text using CodeMirror transactions
- 13 built-in commands with text templates
UI/UX:
- Styled palette with gradient selection indicator
- Smooth animations and transitions
- Accessible keyboard navigation
- Auto-closes on selection or Escape key
Slash Commands
The editor includes a slash command system integrated with CodeMirror 6:
- Type
/at the start of a line to trigger the command palette - Available commands (14 total):
- Headings: h1, h2, h3 - Insert Markdown headers
- Formatting: bold, italic, code - Text formatting
- Blocks: codeblock, quote, hr, table - Block-level elements
- Lists: list - Unordered list
- Dynamic: date - Insert current date in French format (DD/MM/YYYY)
- Links:
link- Insert standard Markdown link[texte](url)ilink- Open internal note linking modal (see Note Linking below)
- Navigate with Arrow Up/Down, select with Enter/Tab, cancel with Escape
- Commands are filtered in real-time as you type after the
/ - The palette is positioned dynamically near the cursor using CodeMirror coordinates
- Implementation in
frontend/src/editor.jswith theSlashCommandsclass - Styled command palette with gradient selection indicator
Note Linking
Implementation: frontend/src/link-inserter.js
The note linking system allows users to create Markdown links between notes without leaving the editor:
Activation: Type /ilink (internal link) in the editor and select the command from the slash palette
Features:
- Fuzzy Search: Real-time search across all notes with 200ms debounce
- Keyboard Navigation: Navigate with ↑/↓, select with Enter, cancel with Esc
- Search Integration: Reuses existing
/api/searchendpoint (no new backend code) - Rich Results: Shows note title, path, tags, and metadata
- Instant Insertion: Inserts
[Note Title](path/to/note.md)format at cursor position
Architecture:
LinkInserterclass manages the search modal and selection- Opens via
SlashCommands.openLinkInserter()when/ilinkis triggered - Uses HTMX search API for consistency
- Modal styled to match
SearchModaldesign language
Workflow:
- User types
/ilink→ slash palette appears - User selects "ilink" → modal opens with search input
- User types search query → fuzzy search filters notes
- User selects note (Enter/click) → Markdown link inserted
- Modal closes → editor regains focus at end of inserted link
Standard Links: For external URLs, use /link to insert the standard Markdown template [texte](url)
Link Format: Links are inserted as HTML with HTMX attributes:
<a href="#" hx-get="/api/notes/path/to/note.md" hx-target="#editor-container" hx-swap="innerHTML">Note Title</a>
This format:
- Clickable in preview: Links open the note directly in the editor when clicked
- HTMX-powered: Uses existing HTMX infrastructure (no new backend code)
- Inline HTML: Marked.js renders the HTML as-is, DOMPurify sanitizes it, HTMX processes it
- Editable: Plain HTML in the source, can be manually edited if needed
Note: This format is specific to this application. For compatibility with other Markdown tools, use standard Markdown links with /link command.
Frontend Libraries
The application uses a mix of npm packages (for the editor) and CDN-loaded libraries (for utilities):
NPM Packages (Built with Vite)
Managed in frontend/package.json:
- @codemirror/basic-setup (^0.20.0): Base editor functionality (line numbers, search, etc.)
- @codemirror/lang-markdown (^6.5.0): Markdown language support and syntax highlighting
- @codemirror/state (^6.5.2): Editor state management
- @codemirror/view (^6.38.6): Editor view layer and rendering
- @codemirror/theme-one-dark (^6.1.3): Dark theme for CodeMirror
- @replit/codemirror-vim (^6.2.2): Vim mode integration for CodeMirror
- vite (^7.2.2): Build tool for bundling frontend modules
CDN Libraries
Loaded in templates/index.html:
- htmx (1.9.10): AJAX interactions and dynamic content loading
- marked.js: Markdown to HTML conversion for preview
- DOMPurify: HTML sanitization to prevent XSS attacks
- Highlight.js (11.9.0): Syntax highlighting for code blocks in preview with Atom One Dark theme
Styling
- 8 Dark Themes: Switchable themes in
static/theme.css- Material Dark, Monokai, Dracula, One Dark, Solarized, Nord, Catppuccin, Everforest
- Color System: CSS custom properties for consistent theming
- Background colors:
--bg-primary,--bg-secondary,--bg-tertiary,--bg-elevated - Text colors:
--text-primary,--text-secondary,--text-muted - Accent colors:
--accent-blue,--accent-violet
- Background colors:
- Font Customization: 8 font families with 4 size presets
- No CSS Framework: All styles hand-crafted with CSS Grid and Flexbox
- Responsive Design: Adaptive layout for different screen sizes
- Custom Scrollbars: Styled scrollbars matching the current theme
Build Output
The Vite build process produces:
static/dist/project-notes-frontend.es.js- ES module format (1.0 MB, includes all CodeMirror 6 dependencies)static/dist/project-notes-frontend.umd.js- UMD format (679 KB, legacy compatibility)
Project Structure
project-notes/
├── cmd/
│ └── server/
│ └── main.go # Server entry point
├── internal/
│ ├── api/
│ │ ├── handler.go # HTTP handlers for CRUD operations
│ │ ├── rest_handler.go # REST API v1 endpoints
│ │ ├── daily_notes.go # Daily notes functionality
│ │ └── favorites.go # Favorites management
│ ├── indexer/
│ │ ├── indexer.go # Note indexing and search
│ │ └── indexer_test.go # Indexer tests
│ └── watcher/
│ └── watcher.go # Filesystem watcher with fsnotify
├── frontend/ # Frontend build system
│ ├── src/
│ │ ├── main.js # Entry point - imports all modules
│ │ ├── editor.js # CodeMirror 6 editor with slash commands
│ │ ├── vim-mode-manager.js # Vim mode integration
│ │ ├── search.js # Search modal (Ctrl/Cmd+K)
│ │ ├── file-tree.js # Drag-and-drop file tree
│ │ ├── favorites.js # Favorites system
│ │ ├── daily-notes.js # Daily notes and calendar widget
│ │ ├── keyboard-shortcuts.js # Global keyboard shortcuts
│ │ ├── theme-manager.js # Theme switching
│ │ ├── font-manager.js # Font customization
│ │ └── ui.js # Sidebar toggle
│ ├── package.json # NPM dependencies
│ ├── package-lock.json
│ └── vite.config.js # Vite build configuration
├── static/
│ ├── dist/ # Compiled frontend (generated)
│ │ ├── project-notes-frontend.es.js
│ │ └── project-notes-frontend.umd.js
│ └── theme.css # Material Darker theme
├── templates/
│ ├── index.html # Main page layout
│ ├── editor.html # Editor component
│ ├── file-tree.html # File tree sidebar
│ ├── search-results.html # Search results
│ └── new-note-prompt.html # New note modal
├── notes/ # Note storage directory
│ ├── *.md # Markdown files with YAML front matter
│ ├── daily/ # Daily notes (YYYY-MM-DD.md)
│ ├── .favorites.json # Favorites list (auto-generated)
│ └── daily-note-template.md # Optional daily note template
├── docs/ # Documentation
│ ├── KEYBOARD_SHORTCUTS.md # Keyboard shortcuts reference
│ ├── DAILY_NOTES.md # Daily notes guide
│ ├── USAGE_GUIDE.md # Complete usage guide
│ └── FREEBSD_BUILD.md # FreeBSD build guide
├── go.mod # Go dependencies
├── go.sum
├── API.md # REST API documentation
└── CLAUDE.md # This file
Key Files to Edit
Backend Development:
cmd/server/main.go- Server initialization and routinginternal/api/handler.go- Main HTML endpoints and request handlinginternal/api/rest_handler.go- REST API v1 endpointsinternal/api/daily_notes.go- Daily notes and calendar functionalityinternal/api/favorites.go- Favorites managementinternal/indexer/indexer.go- Search and indexing logicinternal/watcher/watcher.go- Filesystem monitoring
Frontend Development:
frontend/src/editor.js- CodeMirror editor, preview, slash commandsfrontend/src/vim-mode-manager.js- Vim mode integrationfrontend/src/search.js- Search modal functionalityfrontend/src/link-inserter.js- Note linking modal for/linkcommandfrontend/src/file-tree.js- File tree interactions and drag-and-dropfrontend/src/favorites.js- Favorites systemfrontend/src/daily-notes.js- Daily notes creation and calendar widgetfrontend/src/keyboard-shortcuts.js- Global keyboard shortcutsfrontend/src/theme-manager.js- Theme switching logicfrontend/src/font-manager.js- Font customization logicfrontend/src/ui.js- UI utilities (sidebar toggle)static/theme.css- Styling and theming (8 themes)templates/*.html- HTML templates (Go template syntax)
Configuration:
frontend/vite.config.js- Frontend build configurationfrontend/package.json- NPM dependencies and scriptsgo.mod- Go dependencies
Important Notes
- Frontend builds are required: The application will not work without compiled JavaScript in
static/dist/ - No hot reload for frontend: Changes to
frontend/src/require runningnpm run buildand refreshing the browser - Backend changes: Require restarting the Go server (
go run ./cmd/server) - Template changes: Require restarting the Go server (templates are pre-parsed at startup)
- CSS changes: Only require browser refresh (loaded via
<link>tag) - Note changes: Automatically detected by filesystem watcher, trigger re-indexing