8.3 KiB
8.3 KiB
Architecture Overview
Hybrid Architecture
Project Notes uses a hybrid architecture that combines the best of multiple paradigms:
Core Components
- Go Backend: Fast, type-safe server handling file operations and indexing
- HTMX: "HTML over the wire" for dynamic interactions with minimal JavaScript
- Modern JavaScript: CodeMirror 6, drag-and-drop, and UI enhancements
- Vite: Modern build tool for efficient JavaScript bundling
Key Design Principles
- Server renders HTML, not JSON (simpler, faster)
- HTMX handles all AJAX and DOM updates (consistent, reliable)
- JavaScript enhances UI (editor, drag-and-drop, animations)
- Event-driven coordination between HTMX and JavaScript
Technology Stack
Backend: Go
net/http: Standard library for the web servergithub.com/fsnotify/fsnotify: For watching file system changes and re-indexinggopkg.in/yaml.v3: For parsing and marshaling YAML front matter- Chi Router: Lightweight, fast HTTP router (implied by usage)
Why Go?
- Fast compilation and execution
- Excellent standard library
- Built-in concurrency
- Single binary deployment
- Cross-platform support (Linux, FreeBSD, macOS, Windows)
Frontend: HTML, CSS, JavaScript
Core Technologies
-
htmx: For dynamic UI interactions without writing much JavaScript
- Declarative AJAX requests
- DOM swapping and updates
- WebSocket support
- Event-driven architecture
-
CodeMirror 6: For the robust Markdown editor
- Extensible architecture
- Syntax highlighting
- Vim mode support
- Custom extensions (slash commands)
-
Vite: For bundling frontend JavaScript modules
- Fast development server
- Optimized production builds
- ES modules support
- Hot module replacement
Supporting Libraries
- marked.js: For client-side Markdown parsing in the preview
- DOMPurify: For sanitizing HTML output from Markdown to prevent XSS vulnerabilities
- Highlight.js: For syntax highlighting in code blocks
- Custom CSS theme: Dark mode inspired by VS Code and GitHub Dark
Why This Stack?
- Minimal JavaScript complexity
- Progressive enhancement
- Fast page loads
- SEO-friendly (server-rendered HTML)
- Easy to understand and maintain
Architecture Patterns
Server-Side Rendering (SSR)
All HTML is rendered on the server using Go's html/template package:
- Initial page loads are fast
- No JavaScript required for basic functionality
- Better SEO and accessibility
Progressive Enhancement
The application works without JavaScript but is enhanced with it:
- Base functionality: Browse notes, view content (no JS)
- HTMX enhancement: Dynamic updates without page reloads
- JavaScript enhancement: Rich editor, drag-and-drop, animations
File-Based Storage
Notes are stored as plain Markdown files with YAML front matter:
---
title: My Note
date: 2025-11-11
last_modified: 2025-11-11:14:30
tags:
- example
- markdown
---
# My Note
Content here...
Benefits:
- No database setup required
- Easy backups (just copy files)
- Version control friendly (Git)
- Human-readable
- Portable (works with any Markdown tool)
In-Memory Indexing
Notes are indexed in memory for fast search:
- Full-text search across title, tags, path, content
- Tag-based filtering
- Path-based navigation
- Real-time updates via file system watcher
Trade-offs:
- Memory usage scales with note count
- Index rebuilt on server restart
- Suitable for personal/small team use (< 10,000 notes)
Request Flow
Reading a Note
Browser → GET /editor?note=path/to/note.md
↓
Go Handler
↓
Read file from disk
↓
Parse front matter
↓
Render HTML template
↓
Browser ← HTML response
↓
CodeMirror initializes
↓
User sees editable note
Saving a Note
Browser → htmx POST /save
↓
Go Handler
↓
Update front matter (last_modified)
↓
Write file to disk
↓
File system watcher detects change
↓
Re-index note
↓
Browser ← Success response
↓
htmx updates UI
Search
Browser → htmx GET /search?q=query
↓
Go Handler
↓
Query in-memory index
↓
Score and rank results
↓
Render search results template
↓
Browser ← HTML fragment
↓
htmx swaps into DOM
Data Flow
Filesystem (notes/) ←→ File Watcher (fsnotify)
↓
Indexer (in-memory)
↓
HTTP Handlers
↓
Templates + HTMX
↓
Browser
↓
CodeMirror Editor
Scalability Considerations
Current Design (Suitable for)
- Personal use: 1-10,000 notes
- Small teams: 2-5 users
- Single server deployment
- Notes up to ~1MB each
Limitations
- No concurrent editing: Last write wins
- In-memory index: Limited by server RAM
- No authentication: Requires reverse proxy
- Single server: No horizontal scaling
Future Enhancements (if needed)
- SQLite for metadata indexing (larger note collections)
- WebSocket for real-time collaboration
- JWT authentication built-in
- Redis for distributed caching
- Object storage for large attachments
Security Model
Current State
- No built-in authentication: Designed for local/private networks
- XSS protection: DOMPurify sanitizes Markdown output
- Path traversal prevention: Input validation on file paths
- CSRF: Not needed (no session-based auth)
Recommended Production Setup
Internet → Reverse Proxy (nginx/Caddy)
↓
Basic Auth / OAuth
↓
Project Notes (Go)
↓
Filesystem (notes/)
Example nginx config:
location / {
auth_basic "Project Notes";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://localhost:8080;
}
Performance Characteristics
Strengths
- Fast page loads: Server-rendered HTML
- Low latency: In-memory indexing
- Efficient search: Pre-indexed content
- Small footprint: ~10-20MB RAM for typical usage
Benchmarks (approximate)
- Note load time: < 50ms
- Search query: < 10ms (1000 notes)
- Save operation: < 100ms
- Index rebuild: < 1s (1000 notes)
Development Workflow
Backend Development
# Run with auto-reload (using air or similar)
air
# Or manual reload
go run ./cmd/server
Frontend Development
# Watch mode (auto-rebuild)
cd frontend
npm run build -- --watch
Testing
# Run all tests
go test ./...
# With coverage
go test -cover ./...
# Specific package
go test -v ./internal/indexer
Deployment Options
1. Simple Binary
# Build
go build -o server ./cmd/server
# Run
./server -addr :8080 -notes-dir ~/notes
2. Systemd Service (Linux)
See FREEBSD_BUILD.md for service examples.
3. Docker (future)
FROM golang:1.22 AS builder
WORKDIR /app
COPY . .
RUN go build -o server ./cmd/server
FROM alpine:latest
RUN apk add --no-cache ca-certificates
COPY --from=builder /app/server /server
COPY --from=builder /app/static /static
COPY --from=builder /app/templates /templates
EXPOSE 8080
CMD ["/server"]
4. Reverse Proxy
Always recommended for production:
- nginx, Caddy, Traefik
- TLS termination
- Authentication
- Rate limiting
- Caching
Documentation
For more detailed information, see:
- ARCHITECTURE.md - Complete system architecture, patterns, and best practices
- CLAUDE.md - Development guide and implementation details
- API.md - REST API documentation
- DAILY_NOTES.md - Daily notes feature guide
- FREEBSD_BUILD.md - FreeBSD deployment guide
- CHANGELOG.md - Version history
Last updated: November 11, 2025