# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Commands ```bash # Build and run go build ./cmd/iblog ./iblog serve [--port 8080] [--root .] # Hot reload during development (uses air) air # serves on :8081 per .air.toml # Run all tests go test ./... # Run a single test go test ./internal/db/... -run TestPostSearch # User management ./iblog user add ./iblog user list ./iblog user passwd ./iblog user delete # Build frontend JS (from assets/lib/ or assets/admin/lib/) cd assets/lib && bun run build cd assets/admin/lib && bun run build ``` ## Architecture iblog is a Go blog engine with an admin UI. It uses a hybrid model: posts are authored via a browser-based editor, stored in SQLite, and then rendered to static HTML files in `public/` for serving. **Data flow:** Admin UI (EditorJS) → SQLite (`data/iblog.db`) → static HTML (`public/`) → served to readers **Key packages:** - `cmd/iblog/` — CLI entry point with `serve` and `user` subcommands - `internal/` (package `auth`) — htpasswd-compatible bcrypt password file; nginx can use the same file via `auth_basic_user_file` - `internal/db/` — SQLite wrapper; schema includes `posts`, `pages`, `redirects`, `settings`, and an FTS5 virtual table (`pages_fts`) for full-text search - `internal/server/` — Gin HTTP handlers: `adminserver.go` (admin CRUD, auth middleware, setup flow), `frontpage.go`, `posthandler.go`, `fileserver.go` - `internal/builder/` — Converts EditorJS block JSON to HTML (`editorjs.go`) - `internal/media/` — Image upload, processing (govips/libvips), and serving **Frontend assets** are embedded into the binary via `embed.go`: - `assets/lib/` — Shared site JS (thumbhash, built with bun → `dist/`) - `assets/admin/lib/` — Admin editor JS (EditorJS + plugins, built with bun → `dist/`) - `assets/components/` — Custom web components served to the public site - `assets/styles/` — CSS - `templates/` — Go `html/template` files; `templates/admin/` for admin UI **Directory layout at runtime** (controlled by `--root`): ``` data/iblog.db SQLite database data/.passwords htpasswd file (bcrypt, 0600) data/media/ uploaded media originals + processed images public/ generated static HTML output components/ optional user-supplied web components styles/ optional user-supplied CSS overrides ``` **Setup flow:** On first run (no password file), all requests redirect to `/setup` where the first admin user is created. After that, `/admin/` routes require HTTP Basic Auth. **Static generation:** Saving a post in the admin UI writes HTML to `public//index.html` and updates the FTS5 index. The `public/` directory is served as a fallback for any route not matched by dynamic handlers. ## Notes - `govips` wraps libvips; libvips must be installed on the host (`brew install vips` on macOS). - The JS bundles in `assets/*/lib/dist/` are committed — rebuild them with bun when changing JS dependencies. - Posts store content as raw EditorJS JSON (`blocks` column) and render to HTML on publish, not on read.