Files
trilium_share_gruvbox/AGENTS.md
T

108 lines
7.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AGENTS.md Trilium Share Gruvbox Blog System
Public repository for the **Gruvbox public-share theme + blog system** that runs on a
[TriliumNext](https://github.com/TriliumNext/Trilium) instance (`notes.familie-zink.org`,
live blog: `richard.familie-zink.org`). This file captures the requirements and design
decisions so future work stays consistent.
## What this is
A blog built on Trilium's Public Share: a backend **blog generator** builds index/category/tag
pages, an RSS feed, a sitemap, a search index and a garden-state map from notes that carry a
`publish=true` label. Frontend `shareHtml` scripts add search, prev/next, reading time,
widget rendering (Mermaid/Excalidraw/MindMap) and a themed footer. All styling lives in one
CSS file (Gruvbox, light + dark, theme toggle without reload).
## Repository layout
| Path | Note in Trilium | Purpose |
|---|---|---|
| `blog_generator.js` | `blog_generator` (backend script) | builds index, categories, tags, feed, sitemap, `blog_data`, `state_map` |
| `blog_publish_manager.js` | `blog_publish_manager` (backend script) | mirrors notes between `Unpublished` and the blog on `publish` label changes |
| `theme/blog_share_theme.css` | `blog_share_theme.css` (`shareCss`) | the entire Gruvbox theme |
| `theme/favicon.svg`, `theme/cookie.woff2` | `favicon`, `Cookie` | site icon + BMC font |
| `lib/highlight.js`, `lib/hljs_line_numbers.js` | `highlight.js`, `hljs line numbers plugin` | code highlighting |
| `scripts/*.js` | one code note each (`.blog`), attached via `~shareHtml` | frontend snippets (verbatim content incl. `<script>`) |
| `templates/blog_article.html` | `Blog Article` | article template with promoted labels |
| `examples/*` | ignis8 icons/script | sample category logo |
| `generated/*` | `feed.xml`, `sitemap.xml`, `blog_data`, `state_map` | regenerated by the generator (reference only) |
| `assets/palette.png` | | Gruvbox palette (from morhetz/gruvbox, MIT) |
## How the generator works (keep this intact)
- Collects notes with `publish=true` under the blog root (skips `blogGarden` subtrees).
- **Index**: page 1 = blog root, further pages as notes under `.blog` named by
`blogPagedFor` + `blogPagedNumber` labels, `shareAlias = <alias>-<n>` (`blog-2`, …).
- **Categories**: any top-level note under the blog root that is not a system note
(`Tags`, `.blog`, `Impressum`, `About Me`, `Search`) is a category; `blogGarden`
marks a growth-state garden. Category pages are paginated the same way.
- **Sorting**: index, categories, tags and `blog_data` are all sorted by publication
date descending (`date` label, fallback `dateCreated`). Never change this.
- **Pagination**: `POSTS_PER_PAGE = 10`. Prev/next on index/category pages link only
between that section's pages (server-side `.blog-pagination`), not globally.
- **Article prev/next** (`scripts/prev_next.js`) is scoped to the article's category
(`blog_data.articles[].category`); falls back to the global list when uncategorized.
- **Menu sorting** (`scripts/menu_date_sort.js`, `shareHtmlLocation=body:end`): reads
`blog_data.articles[].date` (generator exposes the `date` label, fallback `dateCreated`,
`YYYY-MM-DD`), re-sorts each category's menu entries by date descending and prefixes the
label with `YYYY-MM-DD <shortened title>` (icons preserved). Non-article entries are left
in place.
- **Thumbnails** (`thumbSrc()`): prefer a child note of the article titled `*_thumb.*`
(e.g. `ngc281_thumb.jpg`) → `api/notes/<id>/download`; otherwise use the first `<img>`
from the note content. Layout: image left, summary right (`.blog-post-inner`),
`max-height:256px`, lazy-loaded. **There is no server-side resizing** see "Limitations".
- Regenerates `feed.xml`, `sitemap.xml`, `state_map` (garden states) and `blog_data`
(search index: id/title/url/summary/tags/category). Sets `shareDescription` from `summary`.
## Wiring / attributes (the ground truth)
- All inheritable relations live on the **blog root**: `~shareCss → blog_share_theme.css`,
`~shareFavicon → favicon`, `~shareHtml → <each script>`, `~runOnNoteContentChange/…
→ blog_generator`, `~runOnAttributeChange/Creation → blog_publish_manager`.
- Every script note carries `shareHtmlLocation` (`head:end`, `body:end`, `content:start`,
`body:start`) and `shareHiddenFromTree`.
- `feed.xml``shareAlias=feed` + `shareRaw`; `sitemap.xml``shareAlias=sitemap.xml` + `shareRaw`.
- Generator + publish manager are `application/javascript;env=backend`; generator has `run=daily`.
- Digital Garden category: `blogGarden`, `label:state` definition
(`promoted,alias=Growth Condition,single,select,options=Seed;Seedling;Sprout;Sprouting;Bud;Evergreen;Draft;Review`, inheritable), `~shareHtml → garden h1 green`.
- On import the note IDs differ → replace the `__X_ID__` tokens in scripts/generator (see README).
## Theme / design rules (keep consistent)
- **Gruvbox palette** only: bg `#282828`/`#1d2021`, fg `#ebdbb2`, red `#fb4934`,
green `#b8bb26`, yellow `#fabd2f`, blue `#83a598`, purple `#d3869b`, aqua `#8ec07c`,
orange `#fe8019`; light-mode fades from Gruvbox Light.
- **Radius system** (user decision, 2026-08-28): `8px` for code blocks/code notes,
inline code, embedded images, diagrams (mermaid/mindmap/excalidraw) and thumbnails;
`10px` for blog cards; `6px` for chips/tags/buttons/inputs; `4px` for tiny menu icons.
Embedded images and inline code use the **same 8px** radius.
- Inline code: `#content code { border-radius:8px; padding:.1em .35em }` (dark bg in both themes).
- Embedded images: `#content img:not(.blog-thumb) { border-radius:8px }`.
- **Figure captions**: `#content figcaption` is a Gruvbox chip (secondary bg, highlight
border, 8px radius, muted italic text, centered).
- Images in the share are served full-size only (no resize endpoint) → keep the
`_thumb` child-note convention for small thumbnails.
- Built-in share footer navigation and book children list are hidden
(`#content-footer .navigation`, `#index`).
## Limitations / gotchas
- **Backend script module whitelist is hardcoded** (`dayjs`, `marked`, `turndown`,
`cheerio`, `axios`, `xml2js`, `escape-html`, `sanitize-html`, `lodash`); `sharp`,
`fs`, `child_process`, `http` etc. are blocked. Therefore **image resizing inside a
backend script is impossible** without patching Trilium source. Do not attempt to add
sharp-based code to the generator.
- Triggering the generator via an attribute change on the **blog root itself** is ignored
by the self-trigger guard (`isGeneratedNoteId(BLOG_ROOT_ID) → true`). To force a full
regeneration, change an attribute/content on a **published article** instead.
- The share never resizes images; the `_thumb` child-note convention is the intended path
for bandwidth-friendly thumbnails.
- Comments/commits in the repo are English; communication with the owner is German.
## Releasing changes
Edit the corresponding Trilium note (live), verify on `richard.familie-zink.org`, then mirror
the anonymized file into this repo (replace `richard.familie-zink.org``https://YOUR-INSTANCE.example.com`,
`Richard's Blog``Your Blog`, and the note-ID tokens → `__…__`), update `README.md` if the
feature list changed, commit and push to `main`. Never commit real note IDs, the ETAPI token,
or personal data (name/domain are allowed in the README demo badge only).