Commit Graph

109 Commits

Author SHA1 Message Date
svemagie
76a13c4441 fix: normalize related to array in seeAlsoLinks filter
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>
2026-03-23 18:53:44 +01:00
svemagie
85beed8ef3 feat: See Also includes in-text links to other blog posts
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>
2026-03-23 18:45:58 +01:00
svemagie
2e416ab2e1 feat: See Also and Linked From sections on posts
- `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>
2026-03-23 18:13:59 +01:00
svemagie
31831c7e02 feat: celebrate evergreen garden stage promotions
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>
2026-03-23 17:47:46 +01:00
svemagie
f7ce951075 fix(listening): copy Funkwhale images in eleventy.after, not passthrough
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>
2026-03-22 07:43:14 +01:00
svemagie
796318e161 feat(listening): cache Funkwhale cover images locally at build time
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>
2026-03-22 07:01:54 +01:00
svemagie
20e4403b00 feat(listening): merge Funkwhale and Last.fm into single sorted timeline
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>
2026-03-21 16:39:00 +01:00
svemagie
3752e23eaf perf: skip unfurl prefetch when no new interaction URLs (manifest cache)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 22:17:26 +01:00
svemagie
9ba7980bc3 perf: memoize hash filter to eliminate redundant disk reads per build
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 22:15:30 +01:00
svemagie
39aaf0b79d perf: add build timing instrumentation to OG and unfurl hooks
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 22:13:41 +01:00
svemagie
498da21ec0 fix: add robots.txt to Eleventy passthrough copy
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>
2026-03-19 15:31:36 +01:00
svemagie
606a7f6b1e fix: use glob patterns for Lora passthrough copy
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>
2026-03-19 15:02:49 +01:00
svemagie
1ed4cb4663 style: serve Lora locally, lighten bg, bump article font size
- 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>
2026-03-19 14:59:03 +01:00
svemagie
66414d8cd6 style: adopt Gruvbox-inspired palette and serif typography
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>
2026-03-19 14:33:58 +01:00
svemagie
d9ac9bffc5 feat: add soft-delete filter and content-warning support
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>
2026-03-19 00:59:19 +01:00
svemagie
07369d9687 fix(ai): remove unused kebab-case ai-text-level/ai-code-level fallbacks
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>
2026-03-17 08:00:24 +01:00
svemagie
571ecb6e40 fix(webmentions): filter out self-interactions from own Bluesky account
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>
2026-03-16 00:59:40 +01:00
svemagie
a166af2306 chore: sync upstream — performance, webmentions v2, OG v3
- _data: switch to cachedFetch wrapper (10s timeout + 4h watch cache)
- js/webmentions.js: owner reply threading, platform provenance badges, DOM dedup, Micropub reply support
- js/comments.js: owner detection, reply system, Alpine.store integration
- _includes/components/webmentions.njk: data-wm-* attrs, provenance badge slots, reply buttons
- _includes/components/comments.njk: owner-aware comment form, threaded replies
- widgets/toc.njk: Alpine.js tocScanner upgrade (replaces is-land/inline-JS)
- lib/og.js + og-cli.js: OG card v3 (light theme, avatar, batched spawn, DESIGN_VERSION=3)
- eleventy.config.js: hasOgImage cache, memoized date filters, batched OG/unfurl, post-build GC, YouTube check opt
- base.njk: Inter font preloads + toc-scanner.js script
- critical.css: font-face declarations (font-display:optional)
- tailwind.css: font-display swap→optional
- tailwind.config.js: prose link colors -700→-600
- Color design system: accent-700/300 → accent-600/400 across components

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 23:56:56 +01:00
svemagie
ba1dba4661 feat: integrate eleventy-plugin-mermaid for diagram support
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>
2026-03-15 13:01:01 +01:00
svemagie
e8ba3b9ae6 feat: nested tags (Obsidian-style) for categories system
Adds hierarchical tag support using "/" separator (e.g. "tech/programming/js").
- New filters: nestedSlugify, categoryMatches, categoryBreadcrumb,
  categoryGroupByRoot, categoryDirectChildren
- categories collection auto-generates ancestor pages for nested tags
- categories.njk: breadcrumb nav, sub-tags section, ancestor-aware post matching
- categories-index.njk: grouped tree view (root + indented children)
- categories widget: shows root tags only with child count badge
- All category links updated from slugify → nestedSlugify (backward-compatible)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 10:56:34 +01:00
svemagie
04b6ed1217 feat: derive gardenStage from nested tags (garden/cultivate)
- 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
2026-03-15 09:41:18 +01:00
svemagie
5259509a3c feat: add evergreen garden stage (🌳)
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>
2026-03-15 08:45:09 +01:00
svemagie
48da3404ea feat: Garden dev 0.1 2026-03-14 16:53:31 +01:00
svemagie
448534799a fix: hide private visibility posts from overview collections
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>
2026-03-12 12:21:52 +01:00
svemagie
9088f3b01d Revert "fix: hide private and where/Loc notes from public overviews and collections"
This reverts commit f04c48e3cb.
2026-03-12 12:01:13 +01:00
svemagie
4e353285b6 Revert "fix: normalize category/tags arrays in isListed and excludeWhereNotes to prevent .map errors"
This reverts commit 841f2650c6.
2026-03-12 12:01:13 +01:00
svemagie
841f2650c6 fix: normalize category/tags arrays in isListed and excludeWhereNotes to prevent .map errors 2026-03-12 11:36:46 +01:00
svemagie
f04c48e3cb fix: hide private and where/Loc notes from public overviews and collections 2026-03-12 11:28:23 +01:00
svemagie
dfb518facd fix: update webmentions feed URL to production domain blog.giersig.eu 2026-03-11 11:29:04 +01:00
svemagie
f31243781f Implement AI frontmatter defaults and metadata outputs 2026-03-09 13:12:13 +01:00
svemagie
182d0fd26e feat(listings): hide unlisted posts from blog and notes 2026-03-08 16:52:54 +01:00
svemagie
13b223ce2a feat(home): hide unlisted posts from recent lists 2026-03-08 16:31:53 +01:00
svemagie
44eca63f10 Merge remote-tracking branch 'theme-upstream/main' 2026-03-07 23:22:52 +01:00
Ricardo
6ff40c8317 perf: address PageSpeed Insights issues (CLS, contrast, touch targets, JS minification)
- Reserve sidebar min-height on desktop to prevent CLS from Alpine.js hydration
- Defer lite-yt-embed.css with media="print" onload pattern
- Add terser JS minification in eleventy.after build hook
- Increase touch target sizing for category pills, facepile avatars, nav items
- Fix text-surface-400 contrast ratio (3.05:1 → 6.23:1) across 20 instances

Confab-Link: http://localhost:8080/sessions/edb1b7b0-da66-4486-bd9c-d1cfa7553b88
2026-03-07 20:13:45 +01:00
Ricardo
e236b4bf65 a11y: comprehensive WCAG 2.1 Level AA accessibility audit
- 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
2026-03-07 18:58:08 +01:00
svemagie
091d54b509 fix: ignore theme/ directory in Eleventy to prevent duplicate permalink conflicts
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 17:33:16 +01:00
Ricardo
95a532b8c1 fix: add explicit width/height attributes to sparkline SVG
SVGs with only a viewBox and no width/height attributes use intrinsic
sizing that can override CSS width:100%. Adding width="100%" height="100%"
and preserveAspectRatio="none" on the SVG element itself ensures the
sparkline fills its container div.

Confab-Link: http://localhost:8080/sessions/0ec83454-d346-4329-8aaf-6b12139bf596
2026-03-07 17:28:29 +01:00
Ricardo
9a9cd2d251 perf: enable lite-yt-embed, optimize avatar, add cache headers
- YouTube embeds now use lite-youtube facade (loads iframe on click,
  ~800 KiB savings per page with embedded videos)
- Avatar resized from 1000x1000 to 400x400 (152 KiB → 39 KiB)
- lite-yt-embed.css max-width changed to 100% for responsive layout
- Removed unused Tailwind primary color palette from CSS bundle

Confab-Link: http://localhost:8080/sessions/edb1b7b0-da66-4486-bd9c-d1cfa7553b88
2026-03-07 17:26:40 +01:00
Ricardo
8baec25b2c feat: blog filter nav, interactions pagination, note unfurl, pagefind improvements
- Replace broken client-side type filter on /blog/ with navigation
  pill links to dedicated collection pages (with post counts)
- Replace Load More with proper prev/next/page-number pagination
  on Interactions inbound tab (20 per page, filter resets page)
- Add auto-unfurl transform for standalone external links in notes
- Exclude Digest and Categories pages from Pagefind search index
- Add Pagefind search filters for post type, year, and category
- Add Pagefind filter metadata to page.njk layout

Confab-Link: http://localhost:8080/sessions/956f4251-b4a9-4bc9-b214-53402ad1fe63
2026-03-06 10:45:55 +01:00
Ricardo
14dcfba50a feat: fix sparkline calculation, redesign with domain colors, add post-graph
- Fix sparkline downward trend by extrapolating partial current month
- Redesign sparkline SVG with gradient fill and responsive sizing
- Apply domain-specific colors (amber/rose/emerald/purple) via currentColor
- Add eleventy-plugin-post-graph for GitHub-style contribution grids
- Homepage: posting activity graph in Tier 2 default layout
- AI page (/ai/): stats dashboard + AI-involved posts graph injected via layout
- New filters: aiPosts (filter by AI level), aiStats (total/count/percentage)

Confab-Link: http://localhost:8080/sessions/956f4251-b4a9-4bc9-b214-53402ad1fe63
2026-03-05 14:21:27 +01:00
Ricardo
91c0816303 feat: convert #hashtags in post content to category links
Adds a markdown-it inline rule that transforms #tag text into
links to /categories/tag/ on-site. Syndication targets (Bluesky,
Mastodon, Bridgy) continue to receive raw #tag text, which their
native facet/hashtag detection handles automatically.

Edge cases handled: headings, hex colors, URL fragments, code
blocks, pure numbers are all excluded from conversion.

Confab-Link: http://localhost:8080/sessions/0ec83454-d346-4329-8aaf-6b12139bf596
2026-03-05 13:46:40 +01:00
Ricardo
59fe05ae47 fix: use pinned property for featuredPosts collection
Renamed from "featured" to "pinned" to avoid conflict with the
"featured" hero image property in MF2/Micropub. Handles both boolean
and string "true" values from YAML frontmatter.

Confab-Link: http://localhost:8080/sessions/bd3f7012-c703-47e9-bfe2-2ad04ce1842d
2026-03-04 19:49:01 +01:00
Ricardo
8cd3c86bfa feat: add featured posts section for homepage builder
Add `featuredPosts` collection filtering posts with `featured: true`
frontmatter. New `featured-posts` section template with type-aware
rendering (articles, notes, photos, bookmarks, etc.) and star icon
header. Registered in homepage-section.njk dispatcher.

To feature a post, add `featured: true` to its frontmatter. Then add
a `{ "type": "featured-posts" }` section to the homepage config.

Confab-Link: http://localhost:8080/sessions/bd3f7012-c703-47e9-bfe2-2ad04ce1842d
2026-03-04 19:26:18 +01:00
Ricardo
b811b43bc2 feat: syndication webhook on incremental builds
Add an eleventy.after hook that triggers syndication immediately after
incremental rebuilds, cutting latency from ~2 min (poller) to ~5 sec.
Uses built-in crypto for HS256 JWT — no new dependencies.

Confab-Link: http://localhost:8080/sessions/d116ad5b-ef8a-424e-9ebe-76c06bef1df6
2026-03-04 17:33:18 +01:00
Ricardo
2ca3e047a4 feat: UI overhaul — accent color, Inter font, widget icons, diversified colors
- Add teal accent color scale and activate Inter font via @font-face
- Neutralize nav/footer hovers from primary blue to surface neutrals
- Apply accent color to hero subtitle, FAB, CTA buttons, card hovers
- Fix reply post-type color from generic primary to distinctive sky blue
- Create centralized icon macro (icon.njk) with 24 reusable SVG icons
- Add per-widget-type icons and colored left-accent borders to all sidebars
- Update .p-category tags from blue to neutral surface with border
- Diversify color vocabulary: red (likes), amber (bookmarks/blogroll),
  green (reposts), purple (funkwhale), sky (replies), orange (subscribe)

Confab-Link: http://localhost:8080/sessions/bd3f7012-c703-47e9-bfe2-2ad04ce1842d
2026-03-04 11:21:39 +01:00
Ricardo
99c9d7e73d fix: make remote image processing optional via PROCESS_REMOTE_IMAGES
Default "false" — adds eleventy:ignore to remote <img> tags via a
posthtml plugin (priority 1) that runs before eleventy-img (priority -1).
Sharp only processes local images, avoiding OOM from downloading and
decoding hundreds of external images.

Set PROCESS_REMOTE_IMAGES=true to restore previous behavior.

Confab-Link: http://localhost:8080/sessions/0ec83454-d346-4329-8aaf-6b12139bf596
2026-03-03 12:23:51 +01:00
Ricardo
d8d1dbfcec fix: prevent watcher OOM by tuning eleventy-img plugin
- transformOnRequest: process images on-demand in watch mode instead
  of all at once during rebuild (same pattern as zachleat.com)
- cacheOptions: cache remote image fetches to disk (1d build, 30d watch)
- concurrency: 4 (down from default ~10 based on CPU count) to limit
  Sharp's native memory usage from parallel image decodes

Root cause: Sharp processes remote images outside V8 heap, so
--max-old-space-size doesn't cap total memory. Large remote images
(e.g. 3072px-wide) at concurrency 10 spike native memory enough
to exceed the 3GB cgroup limit.

Confab-Link: http://localhost:8080/sessions/0ec83454-d346-4329-8aaf-6b12139bf596
2026-03-03 12:06:46 +01:00
Ricardo
4fb7e2e92e fix: sync new OG images to output during incremental builds
During watcher/incremental builds, .cache/og is in watchIgnores so
Eleventy's passthrough copy doesn't pick up newly generated OG images.
After OG generation, manually copy any new .png files from .cache/og/
to _site/og/ so they're immediately available to serve.

Confab-Link: http://localhost:8080/sessions/956f4251-b4a9-4bc9-b214-53402ad1fe63
2026-03-02 16:04:31 +01:00
Ricardo
a39b20375d fix: make starred page client-side rendered to avoid OOM
5,137 starred repos in Nunjucks template + Pagefind indexing exceeded
the 2048MB Eleventy heap limit during build. Switched to Alpine.js
client-side rendering:

- _data/githubStarred.js: returns only buildDate (no API fetch)
- starred.njk: fetches /githubapi/api/starred/all via Alpine.js
- Added client-side text search (replaces separate Pagefind index)
- Removed pagefind-starred build step and --exclude-selectors flag

Confab-Link: http://localhost:8080/sessions/b130e9e5-4723-435d-8d5a-fc38113381c9
2026-03-02 13:40:33 +01:00
Ricardo
9d29f24d93 feat: add /github/starred/ page with Pagefind search and live updates
- New starred.njk page rendering all ~5k starred repos as searchable cards
- Separate Pagefind index (pagefind-starred) for starred-only search
- Alpine.js live updates section for stars added since last build
- Load More pagination (50 at a time, all in DOM)
- githubStarred.js data file fetching from plugin API (1d cache)
- Link from /github/ to /github/starred/
- Exclude starred cards from main site Pagefind index

Confab-Link: http://localhost:8080/sessions/b130e9e5-4723-435d-8d5a-fc38113381c9
2026-03-02 13:15:12 +01:00