6.9 KiB
AGENTS.md – Trilium Share Gruvbox Blog System
Public repository for the Gruvbox public-share theme + blog system that runs on a
TriliumNext 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=trueunder the blog root (skipsblogGardensubtrees). - Index: page 1 = blog root, further pages as notes under
.blognamed byblogPagedFor+blogPagedNumberlabels,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;blogGardenmarks a growth-state garden. Category pages are paginated the same way. - Sorting: index, categories, tags and
blog_dataare all sorted by publication date descending (datelabel, fallbackdateCreated). 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. - 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) andblog_data(search index: id/title/url/summary/tags/category). SetsshareDescriptionfromsummary.
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) andshareHiddenFromTree. feed.xml→shareAlias=feed+shareRaw;sitemap.xml→shareAlias=sitemap.xml+shareRaw.- Generator + publish manager are
application/javascript;env=backend; generator hasrun=daily. - Digital Garden category:
blogGarden,label:statedefinition (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):
8pxfor code blocks/code notes, inline code, embedded images, diagrams (mermaid/mindmap/excalidraw) and thumbnails;10pxfor blog cards;6pxfor chips/tags/buttons/inputs;4pxfor 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 figcaptionis 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
_thumbchild-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,httpetc. 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
_thumbchild-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).