The cache was written to .cache/og/ relative to the workspace, which is
under /usr/local/git/.cache/act/<unique-hash>/hostexecutor/ — a new path
per run, so every build regenerated all images from scratch.
OG_CACHE_DIR env var now controls the cache path (resolved to an absolute
path). CI sets it to /usr/local/git/.cache/og, which survives between runs.
Locally it still defaults to .cache/og inside the project dir.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
og-fix transform was matching date-based URL segments
(/type/yyyy/MM/dd/slug/) that this site never uses — posts live at
/type/slug/. Every post therefore fell through to the default OG image.
Fixed by updating the regex to /type/slug/index.html and deriving the OG
slug as the bare last URL segment, which matches the filename og.js
already generates. The ogSlug filter is simplified accordingly.
Funkwhale GC bug: gcFunkwhaleImages() deleted the entire image cache
whenever _activeFilenames was empty — which happens if the API returns
valid stats but no listenings with cover URLs. Guard added: GC is
skipped when no images were referenced this build.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
OwnYourSwarm checkin posts (visibility: unlisted) were still appearing
in /digest pages. Add isListed filter to the weeklyDigests collection.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Step 3b was matching all div.e-content on the page, including sidebar
component cards (prose-sm). Added prose-lg guard so asides are only
inserted into the article body's e-content.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Browsers re-parent <aside> out of <span class="sidenote-host"> when
parsing (block element inside phrasing content is invalid HTML). This
caused s.parentElement to be .e-content instead of .sidenote-host,
so getBoundingClientRect returned .e-content's top for every sidenote.
Fix: add data-fn-ref="fnrefN" to each <aside class="sidenote"> in the
PostHTML transform. JS looks up document.getElementById(data-fn-ref)
to find the .footnote-ref-num span still inside .sidenote-host, then
measures that element's top for correct vertical alignment.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Instead of relying on CSS cascade to apply position:relative and overflow
to .e-content/.main-content (which may not fire in time or may be overridden),
the positioning script now sets these inline styles itself. Uses
getBoundingClientRect() subtraction (hRect.top - eRect.top) to measure
position of each .sidenote-host relative to .e-content — viewport-relative
and scroll-invariant. Clears inline styles on resize to < 1440px.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
getBoundingClientRect() is viewport-relative; subtracting parent.top was
unreliable depending on scroll position at call time. Switch to
h.offsetTop, which gives distance from .sidenote-host to .e-content's
padding edge directly (because .e-content is position:relative = offsetParent).
Also replace DOMContentLoaded listener (already fired at script injection time)
with requestAnimationFrame for immediate post-paint positioning.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace float+padding-left approach (which narrowed article text) with
position:absolute on each sidenote, placing it to the right of 100% of
.e-content so it paints in the existing left page margin. Text width is
unchanged. Requires viewport ≥ 1440px where the margin is 224px (210px
needed). JS sets each sidenote's top relative to its reference span via
getBoundingClientRect, with 8px overlap prevention.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a PostHTML transform that converts markdown-it-footnote output into
margin sidenotes. Replaces <sup class="footnote-ref"> with a sidenote-host
span containing a numbered inline marker and a floating <aside>. Also adds
has-sidenotes class to the parent <article> when sidenotes are present.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Switch from KittyGiraudel's shortcode-based footnotes plugin to
markdown-it-footnote, which handles standard [^1] Markdown syntax
used in Obsidian notes. Remove the {% footnotes %} shortcode from
the post layout as the plugin renders footnotes automatically.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Registers the KittyGiraudel footnotes plugin and adds {% footnotes %}
to post.njk below the article content.
Usage in content:
{% footnoteref "id" "Footnote text here" %}anchor text{% endfootnoteref %}
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Indiekit stores a single related URL as a plain string, not a YAML list.
Iterating over a string yields characters, breaking the See Also section.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds seeAlsoLinks filter that extracts all internal blog.giersig.eu
links from the raw markdown source and merges them with the explicit
`related` frontmatter field, deduplicated. The section now surfaces
automatically whenever an article links to another post inline.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- `backlinksWith` filter scans raw source files to find posts that
link to the current post (backlinks), with per-build caching.
- `postByUrl` filter looks up a post by absolute URL for title display.
- post.njk: "See Also" renders resolved `related` URLs with titles;
"Linked From" lists backlinks computed at build time.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a "Recently Evergreened" section to /garden/ showing posts that
reached evergreen status within the last 90 days, with a dedicated
green celebration card style.
- New `recentEvergreens` Eleventy collection (evergreeSince within 90d)
- garden.njk: conditional celebration section above the stage groups
- tailwind.css: .garden-evergreen-celebration card (evergreen palette)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Passthrough copy runs before the data cascade, so .cache/funkwhale-images/
is empty when Eleventy processes it. Moving the copy to eleventy.after
guarantees images are downloaded before they're copied to _site/.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Wasabi S3 presigned URLs expire after 1 hour, causing broken images on
the listening page. Download cover art at build time, serve from
/images/funkwhale-cache/, and GC any images no longer referenced by
current listening/favorites data.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a `mergeListens` Eleventy filter that combines both sources into one
array sorted newest-first by timestamp (listenedAt / scrobbledAt). The
Recent Listens section now renders a unified chronological feed with
per-source badges and Alpine filter tabs still working.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Was present in the repo but not copied to _site/ during build,
so it got wiped on every deploy.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Individual file → "fonts" mappings were treated as a single output
file path, causing a conflict. Use glob patterns (like Inter) so
Eleventy treats the destination as a directory.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Install @fontsource/lora and serve latin/latin-ext woff2 files
(weights 400/700, normal + italic) via Eleventy passthrough copy
- Lora now leads the serif font stack in Tailwind and critical CSS,
with Iowan Old Style / Palatino as system-font fallbacks
- Light-mode background lightened: #fbf1c7 → #fefcf0 (still warm,
noticeably less yellow)
- Article prose bumped: post.njk prose-lg, page.njk prose-xl
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Inspired by brennan.day — warm cream backgrounds (#fbf1c7),
Iowan Old Style/Palatino serif font, Gruvbox blue accent (#076678),
and matching code syntax theme in both light and dark modes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Filter posts with `deleted: true` from all collections so soft-deleted
posts no longer appear on the blog. Add content-warning support: on
listing pages, CW posts show a warning label instead of content; on
single post pages, content is wrapped in a collapsible <details>.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The kebab-case keys were never reachable from Nunjucks templates anyway;
camelCase and snake_case cover all actual frontmatter variants.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Exclude webmentions from svemagie.bsky.social / did:plc:g4utqyolpyb5zpwwodmm3hht
at both build-time (eleventy filter) and client-side (webmentions.js).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds @kevingimbel/eleventy-plugin-mermaid so mermaid fenced code blocks
render as interactive diagrams in the browser.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- eleventyComputed in content.11tydata.js resolves gardenStage from
category/tags at build time — no explicit gardenStage frontmatter needed
- withoutGardenTags filter strips garden/* from category pill rendering
- categories collection excludes garden/* entries (no phantom category pages)
- All list templates and post layout use withoutGardenTags filter
Inspired by Maggie Appleton / Andy Matuschak — evergreen notes are
mature and reasonably complete but still alive and growing.
Sits between cultivate and question in the stage order.
Rendered in teal to distinguish from the green seedling/growing stages.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Extend isListed helper to exclude both unlisted and private visibility,
so "where" check-in notes (tagged where, used for /where and /been) no
longer appear in listedNotes, listedPosts, or excludeUnlistedPosts.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add skip-to-main-content link and main content ID target
- Add prefers-reduced-motion media queries for all animations
- Enhance visible focus indicators (2px offset, high-contrast ring)
- Replace ~160 text-surface-500 instances with text-surface-600/dark:text-surface-400
for 4.5:1+ contrast ratio compliance
- Add aria-hidden="true" to ~30+ decorative SVG icons across sidebars/widgets
- Convert facepile containers from div to semantic ul/li with role="list"
- Add aria-label to icon-only buttons (share, sort controls)
- Add sr-only labels to form inputs (webmention, search)
- Add aria-live="polite" to dynamically loaded webmentions
- Add aria-label with relative+absolute date to time-difference component
- Add keyboard handlers (Enter/Space) to custom interactive elements
- Add aria-label to nav landmarks (table of contents)
- Fix modal focus trap and dialog accessibility
- Fix lightbox keyboard navigation and screen reader announcements
Confab-Link: http://localhost:8080/sessions/edb1b7b0-da66-4486-bd9c-d1cfa7553b88