From e974eb6f3feb06c8951f85c1d34161938905f807 Mon Sep 17 00:00:00 2001 From: grm Date: Sat, 12 Sep 2026 19:47:28 +0300 Subject: Add a favicon and rework the Design page Blogs had no icon at all, and browsers probing /favicon.ico ended up rendering the 404 page. Ship a default paper & ink icon (svg + png) and let each blog replace it from the Design page; /favicon.ico now serves the default or redirects to the blog's own image. ICO uploads accepted. The Design page gains colour schemes, reset to defaults, thumbnail image pickers, jump links and a sticky save bar, plus new options: heading font, link underline/hover, content box style and padding, header image height, post dates and format, footer RSS toggle, menu alignment/style/hover and sidebar width. The Menu card picks the position with illustrated tiles and shows only the options that apply to it, using CSS :checked rules rather than JavaScript. All new defaults reproduce the previous look, so existing blogs are unchanged until edited. Theme is jsonb, so no migration. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Sd8UPWrvyYCLj97JexNw3A --- AGENTS.md | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'AGENTS.md') diff --git a/AGENTS.md b/AGENTS.md index 2352b85..b552615 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -86,9 +86,27 @@ internal/web/ server.go (host router, middleware, render helpers) value to an allowlist (hex colours, enum strings, uuid image ids) — this is what makes inlining the generated CSS safe. Add new options in the struct, `normalize`, `ThemeFromForm`, the CSS template and - `dashboard/design.html`. + `dashboard/design.html`; defaults must reproduce the look blogs had + before the option existed. Non-CSS options (`ShowDates`, `DateFormat` via + `FormatDate`, `FooterShowRSS`, `Favicon`) are read by the blog templates. + Optional colours (`LinkHover`, `NavHover`) are `""` = inherit and come + from a colour input paired with a `_custom` checkbox. Image fields + use the `imagepick` partial's radios: `none` clears, a uuid selects, no + value keeps (`pickImage`); an upload in `_file` wins. + Options that only apply to one menu layout (`NavAlign` for horizontal + menus, `NavSidebarWidth` for the sidebar) are shown/hidden in + `design.html` with CSS only (`#np-*:checked ~ .only-*` in dashboard.css, + same trick for the `_custom` hover checkboxes) — no JS, and browsers + without `:checked` just show everything. + `Presets()`/`WithPreset` are the colour schemes (`POST /b/{sub}/design/preset`, + colours only); `POST /b/{sub}/design/reset` stores `DefaultTheme()`. +- **Favicon**: `static/favicon.svg` + `favicon.png` are the defaults, linked + from both layouts. A blog can set `theme.favicon` (an image id) which the + blog layout links instead. `GET /favicon.ico` on every host + (`handleFavicon`) serves the png or redirects to the blog's image, so + icon-probing browsers never hit the 404 page; `favicon.ico` is reserved. - **Images**: `/media/{uuid}` served on every host with immutable cache - headers. Uploads are content-sniffed (png/jpeg/gif/webp). Deleting an + headers. Uploads are content-sniffed (png/jpeg/gif/webp/ico). Deleting an image clears theme references to it. `POST /b/{sub}/images/upload` answers JSON (`{id, filename, markdown}` / `{error}`) when the request has `Accept: application/json`; that is what the editor script calls. -- cgit v1.2.3