diff options
| author | ivar <i@oiee.no> | 2026-04-03 14:22:23 +0200 |
|---|---|---|
| committer | ivar <i@oiee.no> | 2026-04-03 14:22:23 +0200 |
| commit | 33310be68544d3381ac6e9899790f4a106e17e8f (patch) | |
| tree | 385102a7216ffba17d054f11032dae4447371d52 /CLAUDE.md | |
| parent | a8914a8f18c345e934bce93b37845a9dfe0ad73e (diff) | |
| download | nebbet.no-33310be68544d3381ac6e9899790f4a106e17e8f.tar.xz nebbet.no-33310be68544d3381ac6e9899790f4a106e17e8f.zip | |
refactor: convert admin handlers to Gin context-based signatures
- Remove old ServeHTTP method (no longer needed with Gin routing)
- Update all 6 handler methods to use *gin.Context instead of http.ResponseWriter, *http.Request
- Convert handler signatures: handleList, handleNew, handleNewPost, handleEdit, handleDelete
- Remove render() helper (use c.HTML() directly)
- Update renderError() to accept gin.Context instead of http.ResponseWriter
- Update postFromForm() to extract form data from gin.Context using c.PostForm()
- Update main.go to use adminSrv.NewServer() and adminSrv.Engine()
- All handlers now use Gin methods: c.HTML(), c.PostForm(), c.Param(), c.Redirect()
- Path parameters now extracted via c.Param("slug") instead of function arguments
- HTTP status codes and error handling fully migrated to Gin patterns
Build verified: go build ./cmd/nebbet succeeds
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Diffstat (limited to 'CLAUDE.md')
| -rw-r--r-- | CLAUDE.md | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..aaede3c --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,172 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +**nebbet** is a static site generator (SSG) with an integrated admin UI for managing blog posts. It compiles markdown content to HTML, maintains metadata and search indices in SQLite, and provides a web interface for post creation/editing without redeploying. + +## Build & Run Commands + +### Build a production site +```bash +go run ./cmd/nebbet build +``` + +### Watch mode (continuous rebuild on file changes) +```bash +go run ./cmd/nebbet watch +``` + +### Development server (watch + live admin UI) +```bash +go run ./cmd/nebbet serve --port 8080 +``` +Visit `http://localhost:8080/admin/` to manage posts. Admin requires a user; create one first: + +### User management +```bash +# Add a user (prompts for password) +go run ./cmd/nebbet user add alice + +# List users +go run ./cmd/nebbet user list + +# Change password +go run ./cmd/nebbet user passwd alice + +# Delete user +go run ./cmd/nebbet user delete alice +``` + +## High-Level Architecture + +### The Build Pipeline + +1. **Source**: Markdown files in `content/` with YAML frontmatter +2. **Parse**: Extract frontmatter (title, date, tags, layout, draft flag) and body +3. **Render**: Convert markdown → HTML using Goldmark with GFM extensions +4. **Process**: Replace component directives with custom element tags +5. **Output**: Write HTML to `public/` using layout templates +6. **Index**: Update two SQLite databases: + - **meta.db**: Page metadata for listing/filtering by tag + - **search.db**: Full-text search index (FTS5) +7. **Watch**: Monitor content, templates, components for changes; rebuild with 150ms debounce + +### Directory Structure + +``` +content/ # Source markdown files (mirrored in public/ as .html) + index.md # Becomes /index.html → / + admin/ # Skipped from build (admin UI only) + posts/ # Blog posts (managed via admin UI) + +public/ # Generated static output + +templates/ # HTML layout templates + base.html # Default page layout + admin.html # Admin template (for future) + +components/ # JavaScript web components + site-greeting.js # Example component + +lib/ # JavaScript import map + libraries + +styles/ # CSS files (served directly, not copied) + +data/ # SQLite databases (created on first build) + meta.db # Page metadata + search.db # Full-text search index +``` + +### Component System + +Components are declared as HTML comments in markdown and converted to custom elements at build time: + +```markdown +<!-- component:site-greeting {"name": "visitor"} --> +``` + +becomes: + +```html +<site-greeting name="visitor"></site-greeting> +``` + +The `components/` directory contains JavaScript modules that define these custom elements. An importmap is auto-generated from `lib/` and injected into each page. + +### Frontmatter Spec + +Supported frontmatter fields (YAML-style): +``` +title: Page Title # Required +date: 2024-03-31 # Optional; ISO date format +tags: tag1, tag2 # Optional; comma-separated or JSON array +layout: base # Optional; template name (default: base) +draft: false # Optional; if true, page is skipped at build time +``` + +## Key Modules + +### `internal/builder/` +- **builder.go**: Core orchestrator (BuildAll, BuildFile, Watch, RemovePage) +- **frontmatter.go**: Parse YAML frontmatter from markdown +- **markdown.go**: Markdown → HTML conversion (Goldmark + GFM) +- **components.go**: Component directive processing (comments → custom elements) +- **importmap.go**: Auto-generate ES module importmap from lib/ + +### `internal/admin/` +- **server.go**: HTTP handlers for listing, creating, editing, and deleting posts +- Uses Basic Auth (htpasswd-compatible bcrypt passwords) +- Serves form UI for post management +- Triggers rebuilds via the builder after create/edit/delete + +### `internal/auth/` +Manages password file (compatible with nginx auth_basic): +- AddUser, DeleteUser, ChangePassword, ListUsers +- Verify passwords with bcrypt.CompareHashAndPassword +- File format: `username:$2a$...` (one per line) + +### `internal/db/` +Two SQLite databases: + +**meta.db** (PageMeta): +- Stores path, title, date, tags, html_path for each page +- Indexed by path and date +- Used for tag filtering and chronological listing + +**search.db** (SearchDB): +- FTS5 virtual table for full-text search +- Tokenizer: porter unicode61 +- Stores path, title, searchable plain-text content + +## Deployment + +### systemd service +See `nebbet.service` for running the watch daemon as a service. Update SITE_ROOT placeholder. + +### nginx configuration +See `nginx.conf` for: +- Public site serving from `public/` +- Admin UI with htpasswd auth (via `.passwords` file) +- Static assets (styles/, components/, lib/) served directly from source +- Clean URLs (/about → /about.html) + +Replace SITE_ROOT with absolute path to project directory. + +## Testing & Debugging + +The watch debounce is 150ms. When developing: +- Markdown changes only rebuild that file (fast) +- Template/component/lib changes trigger full rebuild +- Multiple simultaneous markdown changes trigger full rebuild (optimization) + +To test the admin UI locally: +```bash +go run ./cmd/nebbet serve +# Create a user first if .passwords doesn't exist +go run ./cmd/nebbet user add admin +# Visit http://localhost:8080/admin/ +``` + +Draft pages (draft: true) are silently skipped during builds but can be tested by removing the draft flag temporarily. |
