diff options
| author | grm <grm@eyesin.space> | 2026-09-12 12:33:57 +0300 |
|---|---|---|
| committer | grm <grm@eyesin.space> | 2026-09-12 12:33:57 +0300 |
| commit | dd13e4b73a105ee416b6cfd8eb19b217622c0031 (patch) | |
| tree | 93ce503a09b99115efeeee6cd1a85781c1674b02 /AGENTS.md | |
| parent | 2b450b66fee4906e746f6e04a6d07a72ff2faf64 (diff) | |
| download | blogspace-dd13e4b73a105ee416b6cfd8eb19b217622c0031.tar.gz blogspace-dd13e4b73a105ee416b6cfd8eb19b217622c0031.tar.bz2 blogspace-dd13e4b73a105ee416b6cfd8eb19b217622c0031.zip | |
Add announcements: blog-wide notices on every page and post
A blog can have any number of announcements ("sections" in the schema):
a book club's next meeting, this month's pick, a holiday closure. Each
has a placement (above or below the posts, or under the menu when the
menu is a left sidebar), a look (highlighted, warning, plain), an order,
and an on/off switch so recurring notices can be kept around while hidden.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Sd8UPWrvyYCLj97JexNw3A
Diffstat (limited to 'AGENTS.md')
| -rw-r--r-- | AGENTS.md | 27 |
1 files changed, 22 insertions, 5 deletions
@@ -23,7 +23,9 @@ table and deployment notes. (e.g. the `<noscript>` button in `posts.html`). - Server-rendered `html/template`; no SPA, no frontend toolchain. - Postgres holds **everything**, including images (`images.data bytea`). -- Posts are Markdown (goldmark → bluemonday). No WYSIWYG. +- Posts are Markdown (goldmark → bluemonday). No WYSIWYG. The editor's + "Insert image" is the one scripted convenience (`partials/editor.html`); + it must keep its no-JS fallback (file appended on save). - Changes are live immediately — there is no draft/preview system. The UX is "save, then refresh your blog tab"; keep the "View blog ↗" links. - Theme customisation is a structured form only; **no custom CSS input**. @@ -36,14 +38,14 @@ table and deployment notes. cmd/blogspace/ main.go (serve|seed|migrate, superadmin + root blog bootstrap), seed.go internal/config/ env → Config; RootSubdomain = "www" internal/db/ pgxpool + goose; migrations/*.sql embedded -internal/store/ models + hand-written SQL (users, blogs, pages, posts, images) +internal/store/ models + hand-written SQL (users, blogs, pages, posts, images, sections) internal/auth/ bcrypt, JWT issue/parse, cookie, HMAC CSRF internal/markdown/ Render(md) → sanitized HTML internal/slug/ Make/Valid/WithSuffix (Greek transliteration included) internal/web/ server.go (host router, middleware, render helpers) - routes.go (all routes), handlers_*.go, theme.go + routes.go (all routes), handlers_*.go (sections = announcements), theme.go templates/ (embedded; layouts/, partials/, auth/, dashboard/, admin/, blog/) - static/ (dashboard.css, blog.css) + static/ (dashboard.css "paper & ink" look — plain CSS, no variables/flex; blog.css) ``` ## Key mechanics @@ -87,7 +89,22 @@ internal/web/ server.go (host router, middleware, render helpers) `dashboard/design.html`. - **Images**: `/media/{uuid}` served on every host with immutable cache headers. Uploads are content-sniffed (png/jpeg/gif/webp). Deleting an - image clears theme references to it. + 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. +- **Editor** (`partials/editor.html`, args via `dict`: name, value, rows, + tall, upload, csrf): textarea + "Insert image" + cheat-sheet. Forms using + it must be `multipart/form-data` and their save handler must call + `s.readUpload(r, "inline_image")` + `appendImageMD` (the no-JS path). +- **Announcements** (`sections` table, `store/sections.go`, + `handlers_sections.go`, `/b/{sub}/announcements…`): per-blog notices with + `placement` (above|below|sidebar), `style` (plain|note|warning), `enabled` + and `sort_order`. `blogView` loads the enabled ones and `splitSections` + routes `sidebar` to the left-sidebar layout only (otherwise above). + Rendered by the `notices` template in `layouts/blog.html`; CSS classes + `notice notice-<style>` use translucent colours so they fit any theme. +- **Dashboard nav**: `dashnav.html` marks the current tab with `hasPrefix + .Path`; a new management section needs a tab there. - **Slugs**: auto-generated from the title; on collision generated slugs get `-2`, `-3`…, user-typed slugs return a 409 with a message. - **Errors**: `store.ErrNotFound` / `store.ErrConflict` are the sentinels |
