diff --git a/CLAUDE.md b/CLAUDE.md index e644fc9..d48ea2c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -21,7 +21,15 @@ 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/search`, `/api/notes/*`, `/api/tree`, `/api/folders/create`, `/api/files/move` +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) 5. Handles static files from `static/` directory ### Frontend @@ -40,6 +48,7 @@ The frontend uses a modern build system with Vite and CodeMirror 6: frontend/src/ ├── main.js # Entry point - imports all modules ├── editor.js # CodeMirror 6 editor implementation with slash commands +├── search.js # Search modal with Ctrl/Cmd+K keyboard shortcut ├── file-tree.js # Drag-and-drop file organization └── ui.js # Sidebar toggle functionality ``` @@ -214,15 +223,64 @@ Rich search supports multiple query formats: - 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 metadata +- `Accept: text/markdown` → Returns raw Markdown content +- `Content-Type: application/json` → Accepts structured JSON request +- `Content-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+K` to open anywhere +- Real-time search with 300ms debounce +- Keyboard navigation: `↑`/`↓` to navigate, `Enter` to open, `Esc` to 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. + ### Security Considerations -File path validation in `handler.go`: +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 `.md` extension 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. diff --git a/README.md b/README.md index f5ca933..29d49ed 100644 --- a/README.md +++ b/README.md @@ -6,14 +6,17 @@ A lightweight, web-based Markdown note-taking application with a Go backend and * **File-based Notes:** All notes are stored as plain Markdown files (`.md`) on the filesystem. * **Tag Indexing:** Notes are indexed by tags specified in their YAML front matter, enabling quick search. -* **Live Markdown Preview:** A side-by-side editor and live preview pane for a better writing experience. +* **CodeMirror 6 Editor:** Modern, powerful Markdown editor with syntax highlighting and One Dark theme. +* **Live Markdown Preview:** Side-by-side editor and live preview pane with scroll synchronization. * **Automatic Front Matter:** Automatically generates and updates `title`, `date` (creation), `last_modified`, and `tags` in YAML front matter. * **Slash Commands:** Insert common Markdown elements and dynamic content (like current date) using `/` commands in the editor. -* **Dynamic File Tree:** An automatically updating file tree in the sidebar to navigate notes. -* **Lightweight Frontend:** Built with htmx for dynamic interactions, minimizing JavaScript complexity. +* **Search Modal:** Press `Ctrl/Cmd+K` to open a powerful search modal with keyboard navigation and real-time results. +* **Dynamic File Tree:** Automatically updating file tree in the sidebar to navigate notes. * **Hierarchical Organization:** Organize notes in folders with drag-and-drop file management. * **Rich Search:** Search by keywords, tags (`tag:projet`), title (`title:meeting`), or path (`path:backend`). -* **Go Backend:** A fast and efficient Go server handles file operations, indexing, and serving the frontend. +* **REST API:** Full REST API (`/api/v1/notes`) for programmatic access - list, read, create, update, and delete notes via HTTP. +* **Lightweight Frontend:** Built with htmx for dynamic interactions, minimizing JavaScript complexity. +* **Go Backend:** Fast and efficient Go server handles file operations, indexing, and serving the frontend. ## Technologies Used @@ -49,17 +52,50 @@ A lightweight, web-based Markdown note-taking application with a Go backend and ### Frontend Build Process -The frontend assets (JavaScript, CSS) are built and optimized using [Vite](https://vitejs.dev/). When changes are made to the frontend source code (e.g., in `frontend/src/`), the `npm run build` command must be executed from the `frontend/` directory. This command compiles, bundles, and minifies the source files into static assets (located in `static/dist/`) that the Go backend serves to the browser. This step is crucial to ensure that the latest frontend changes are reflected in the application. +**IMPORTANT**: The frontend must be built before running the application. + +The frontend uses [Vite](https://vitejs.dev/) to bundle CodeMirror 6 and other JavaScript modules. This step is **required** for the editor to work. + +1. **Install Node.js dependencies** (first time only): + ```bash + cd frontend + npm install + ``` + +2. **Build the frontend**: + ```bash + npm run build + ``` + + This compiles `frontend/src/` files into `static/dist/` (served by Go). + +3. **Development mode** (auto-rebuild on changes): + ```bash + npm run build -- --watch + ``` ### Running the Application -To start the Go backend server: +1. **Build the frontend** (see above, required!) +2. **Start the Go backend server**: + ```bash + go run ./cmd/server + ``` + +3. **Access the application** at `http://localhost:8080` + +**Production build**: ```bash -go run ./cmd/server -``` +# Build frontend +cd frontend && npm run build && cd .. -The application will be accessible in your web browser at `http://localhost:8080`. +# Compile Go binary +go build -o server ./cmd/server + +# Run +./server +``` ## Usage @@ -79,8 +115,12 @@ The application will be accessible in your web browser at `http://localhost:8080 ### Searching Notes -The search supports multiple query formats: +**Quick Search Modal** (Recommended): +1. Press **`Ctrl/Cmd+K`** anywhere to open the search modal. +2. Type your query - results appear instantly with keyboard navigation. +3. Use **`↑`/`↓`** to navigate, **`Enter`** to open, **`Esc`** to close. +**Search Syntax** (works in both modal and header search): 1. **General search:** Type keywords to search across title, tags, path, and content. 2. **Tag filter:** Use `tag:projet` to filter by specific tags. 3. **Title filter:** Use `title:meeting` to search within note titles. @@ -123,3 +163,64 @@ Example: ```bash go run ./cmd/server -addr :3000 -notes-dir ~/my-notes ``` + +## REST API + +Project Notes includes a full REST API for programmatic access to your notes. + +**Base URL**: `http://localhost:8080/api/v1` + +### Quick Examples + +**List all notes**: +```bash +curl http://localhost:8080/api/v1/notes +``` + +**Get a specific note** (JSON): +```bash +curl http://localhost:8080/api/v1/notes/projet/backend.md +``` + +**Get note as Markdown**: +```bash +curl http://localhost:8080/api/v1/notes/projet/backend.md \ + -H "Accept: text/markdown" +``` + +**Create/Update a note**: +```bash +curl -X PUT http://localhost:8080/api/v1/notes/test.md \ + -H "Content-Type: application/json" \ + -d '{ + "body": "\n# Test\n\nContent here...", + "frontMatter": { + "title": "Test Note", + "tags": ["test"] + } + }' +``` + +**Delete a note**: +```bash +curl -X DELETE http://localhost:8080/api/v1/notes/old-note.md +``` + +### Full API Documentation + +See **[API.md](./API.md)** for complete documentation including: +- All endpoints (LIST, GET, PUT, DELETE) +- Request/response formats +- Content negotiation (JSON/Markdown) +- Advanced examples (sync, backup, automation) +- Integration guides + +### Use Cases + +- **Backup**: Automate note backups with cron jobs +- **Sync**: Synchronize notes across machines +- **Integration**: Connect with other tools (Obsidian, Notion, etc.) +- **Automation**: Create notes programmatically (daily notes, templates) +- **CI/CD**: Validate Markdown in pipelines + +**⚠️ Security Note**: The API currently has no authentication. Use a reverse proxy (nginx, Caddy) with auth if exposing publicly. diff --git a/cmd/server/main.go b/cmd/server/main.go index 8845758..b4cd879 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -66,6 +66,8 @@ func main() { }) apiHandler := api.NewHandler(*notesDir, idx, templates, logger) + mux.Handle("/api/v1/notes", apiHandler) // REST API v1 + mux.Handle("/api/v1/notes/", apiHandler) // REST API v1 mux.Handle("/api/search", apiHandler) mux.Handle("/api/folders/create", apiHandler) mux.Handle("/api/files/move", apiHandler) diff --git a/server b/server index 54fc764..e222fac 100755 Binary files a/server and b/server differ