diff options
Diffstat (limited to 'AGENTS.md')
| -rw-r--r-- | AGENTS.md | 28 |
1 files changed, 22 insertions, 6 deletions
@@ -103,7 +103,8 @@ internal/web/ server.go (host router, middleware, render helpers) is a single segment on purpose (a `/static/` prefix pattern conflicts with `/{page}/{post}`); static files must stay flat. The public `GET /tag/{tag}` is a literal first segment, so it beats `/{page}/{post}` - on every host (`tag` is reserved too). A `{page}` wildcard never matches + on every host (`tag` is reserved too), and so is `GET /search` (`search` + reserved). A `{page}` wildcard never matches a trailing slash, so listings put `?p=N` straight after `base` (`/`, `/news`, `/tag/go`) — `/news/?p=2` would be a 404. - **Auth**: login lives only at `/webadmin` on the root domain (deliberately @@ -155,9 +156,11 @@ internal/web/ server.go (host router, middleware, render helpers) `handlers_layout.go`, `/b/{sub}/layout…`): a blog page is six areas — `header`, `left`, `above`, `below` (the two custom-HTML slots inside the main column, one module at most), `right`, `footer` — each an ordered - list of modules (`kind`: title, logo, menu, archive, recent, tags, - tagcloud, html, rss, text, sitemap; `moduleKinds` says which kinds an area - accepts). Modules have an optional `title` (heading), `body` (raw HTML or + list of modules (`kind`: title, logo, menu, search, archive, recent, tags, + tagcloud, html, rss, text, sitemap — the list is also a CHECK constraint + on `modules.kind`, so a new kind needs a migration; `moduleKinds` says + which kinds an area accepts; `moduleHasSettings` takes the module because a header search box + has nothing to edit). Modules have an optional `title` (heading), `body` (raw HTML or footer text) and `count` (recent posts; tags to list, 0 = all). `blogView` builds a `Layout` (`buildLayout`, areas that are switched off are dropped) and only fetches the archive index / recent posts / tag counts when a @@ -291,6 +294,19 @@ internal/web/ server.go (host router, middleware, render helpers) which also holds the article loop + pager shared by `blog/page.html` and `blog/tag.html`); the two modules are `tags` (by use, `count`) and `tagcloud` (alphabetical, `cloudSizes` → `tc-1…tc-5`). +- **Search** (`web/search.go`, `handleBlogSearch`, `GET /search?q=&p=`, + `blog/search.html`): the `search` module is a plain GET form (header bar or + side box, `searchform` in `layouts/blog.html`; the results page shows one + too). `searchPattern` turns the query into the regex both Postgres and Go + run: words `regexp.QuoteMeta`'d and joined with `.*`, so the reader's words + are literal, case does not matter (`~*` / `(?is)`) and spaces mean + "anything in between", in order. `SearchPublishedPosts` matches it against + `title || '\n' || body_md` of published posts from every page, 20 per page + (`searchPerPage`); queries are cut at 100 runes. Results are title, date + and `searchSnippet` (the Markdown around the first match, escaped, the + match in `<mark>`; the body's start when only the title matched). A blank + or unmatched query is a normal 200, not a 404; the pager is the page's + own (`&p=N` after `?q=`), not the `postlist` one. - **Slugs**: auto-generated from the title; on collision generated slugs get `-2`, `-3`…, user-typed slugs return a 409 with a message. `slug.Clean` is `Make` without the "untitled" fallback, for inputs that @@ -322,7 +338,7 @@ superadmin password to `admin`. Production refuses both. `internal/db/migrations/control/` for users and the registry; goose `-- +goose Up/Down` sections; they run automatically at startup. Never edit an applied migration. Blog chain so far: `00001_init`, `00002_language`, - `00003_files`, `00004_tags`; control: `00001_init`, `00002_upload_limit`. Both chains were re-baselined at 00001 after + `00003_files`, `00004_tags`, `00005_search`; control: `00001_init`, `00002_upload_limit`. Both chains were re-baselined at 00001 after the move to per-blog databases; deployments from before it have `goose_db_version` rows 2–7 in the control DB that must be deleted once (README "Upgrading from a single database") or the next control migration @@ -338,5 +354,5 @@ superadmin password to `admin`. Production refuses both. ## Things deliberately not built (ask before adding) Drafts/preview, custom CSS, comments, multiple blogs per user, email, -user self-registration, custom domains per blog, image resizing, search, +user self-registration, custom domains per blog, image resizing, sanitising the custom HTML module (owner's decision, see above). |
