From 48da3404eaf3a78a8d0431aaeec3fe916b8cabf0 Mon Sep 17 00:00:00 2001 From: svemagie <869694+svemagie@users.noreply.github.com> Date: Sat, 14 Mar 2026 16:53:31 +0100 Subject: [PATCH] feat: Garden dev 0.1 --- _includes/components/garden-badge.njk | 18 +++++ _includes/layouts/post.njk | 5 ++ css/tailwind.css | 45 +++++++++++ eleventy.config.js | 31 ++++++++ garden.njk | 105 ++++++++++++++++++++++++++ 5 files changed, 204 insertions(+) create mode 100644 _includes/components/garden-badge.njk create mode 100644 garden.njk diff --git a/_includes/components/garden-badge.njk b/_includes/components/garden-badge.njk new file mode 100644 index 0000000..b63a328 --- /dev/null +++ b/_includes/components/garden-badge.njk @@ -0,0 +1,18 @@ +{# + garden-badge.njk — Digital Garden stage indicator + Usage: {% include "components/garden-badge.njk" %} + Requires: gardenStage variable in scope (from post frontmatter) + Renders a coloured pill badge linking to /garden/# +#} +{% if gardenStage %} +{% set _stageInfo = gardenStage | gardenStageInfo %} +{% if _stageInfo %} + + + {{ _stageInfo.label }} + +{% endif %} +{% endif %} diff --git a/_includes/layouts/post.njk b/_includes/layouts/post.njk index 6ebfcb3..34439f6 100644 --- a/_includes/layouts/post.njk +++ b/_includes/layouts/post.njk @@ -43,6 +43,8 @@ withBlogSidebar: true {% endif %} {% endif %} + {# Digital Garden stage badge #} + {% include "components/garden-badge.njk" %} {# Bridgy syndication content - controls what gets posted to social networks #} @@ -228,6 +230,9 @@ withBlogSidebar: true {{ aiTextLevel }} {{ aiCodeLevel or "0" }} {% if aiUsed %}yes{% else %}no{% endif %} + {% if gardenStage %} + {{ gardenStage }} + {% endif %} {% if category %} {% if category is string %} {{ category }} diff --git a/css/tailwind.css b/css/tailwind.css index 7adc546..136de17 100644 --- a/css/tailwind.css +++ b/css/tailwind.css @@ -986,3 +986,48 @@ body[data-indiekit-auth="true"] .share-post-btn:hover { background: #374151; color: #34d399; } + +/* ============================================================ + Digital Garden — stage badges + Used by _includes/components/garden-badge.njk + Stages: plant · cultivate · question · repot · revitalize · revisit + ============================================================ */ +@layer components { + .garden-badge { + @apply inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium border no-underline transition-colors; + } + .garden-badge--plant { + @apply bg-green-100 text-green-800 border-green-200 hover:bg-green-200 + dark:bg-green-900/30 dark:text-green-300 dark:border-green-800 dark:hover:bg-green-900/50; + } + .garden-badge--cultivate { + @apply bg-emerald-100 text-emerald-800 border-emerald-200 hover:bg-emerald-200 + dark:bg-emerald-900/30 dark:text-emerald-300 dark:border-emerald-800 dark:hover:bg-emerald-900/50; + } + .garden-badge--question { + @apply bg-yellow-100 text-yellow-800 border-yellow-200 hover:bg-yellow-200 + dark:bg-yellow-900/30 dark:text-yellow-300 dark:border-yellow-800 dark:hover:bg-yellow-900/50; + } + .garden-badge--repot { + @apply bg-orange-100 text-orange-800 border-orange-200 hover:bg-orange-200 + dark:bg-orange-900/30 dark:text-orange-300 dark:border-orange-800 dark:hover:bg-orange-900/50; + } + .garden-badge--revitalize { + @apply bg-purple-100 text-purple-800 border-purple-200 hover:bg-purple-200 + dark:bg-purple-900/30 dark:text-purple-300 dark:border-purple-800 dark:hover:bg-purple-900/50; + } + .garden-badge--revisit { + @apply bg-blue-100 text-blue-800 border-blue-200 hover:bg-blue-200 + dark:bg-blue-900/30 dark:text-blue-300 dark:border-blue-800 dark:hover:bg-blue-900/50; + } +} + +/* Digital Garden index page — post card in garden listing */ +@layer components { + .garden-post-card { + @apply p-3 rounded-lg border border-surface-200 dark:border-surface-700 + hover:border-surface-300 dark:hover:border-surface-600 + hover:bg-surface-50 dark:hover:bg-surface-800/50 + transition-colors; + } +} diff --git a/eleventy.config.js b/eleventy.config.js index aaa72a1..b61f469 100644 --- a/eleventy.config.js +++ b/eleventy.config.js @@ -927,6 +927,28 @@ export default function (eleventyConfig) { return posts.filter(isListed); }); + // ── Digital Garden ─────────────────────────────────────────────────────── + // Returns display metadata for a garden stage slug. + // Used by garden-badge.njk and garden.njk to render labels + emoji. + // Stages map to Obsidian's #garden/* tag convention: + // #garden/plant → gardenStage: plant (newly planted idea) + // #garden/cultivate → gardenStage: cultivate (actively developing) + // #garden/question → gardenStage: question (open exploration) + // #garden/repot → gardenStage: repot (being restructured) + // #garden/revitalize → gardenStage: revitalize (being refreshed) + // #garden/revisit → gardenStage: revisit (flagged for revisiting) + eleventyConfig.addFilter("gardenStageInfo", (stage) => { + const stages = { + plant: { label: "Seedling", emoji: "🌱", description: "Newly planted idea" }, + cultivate: { label: "Growing", emoji: "🌿", description: "Being actively developed" }, + question: { label: "Open Question", emoji: "❓", description: "Open for exploration" }, + repot: { label: "Repotting", emoji: "🪴", description: "Being restructured" }, + revitalize: { label: "Revitalizing", emoji: "✨", description: "Being refreshed and updated" }, + revisit: { label: "Revisit", emoji: "🔄", description: "Flagged for revisiting" }, + }; + return stages[stage] || null; + }); + // Collections for different post types // Note: content path is content/ due to symlink structure // "posts" shows ALL content types combined @@ -1093,6 +1115,15 @@ export default function (eleventyConfig) { .sort((a, b) => b.date - a.date); }); + // Digital Garden — posts with a gardenStage frontmatter property + eleventyConfig.addCollection("gardenPosts", function (collectionApi) { + return collectionApi + .getFilteredByGlob("content/**/*.md") + .filter(isPublished) + .filter((item) => item.data.gardenStage) + .sort((a, b) => b.date - a.date); + }); + // Weekly digests — posts grouped by ISO week for digest pages and RSS feed eleventyConfig.addCollection("weeklyDigests", function (collectionApi) { const allPosts = collectionApi diff --git a/garden.njk b/garden.njk new file mode 100644 index 0000000..51e5522 --- /dev/null +++ b/garden.njk @@ -0,0 +1,105 @@ +--- +layout: layouts/base.njk +title: Digital Garden +withSidebar: true +permalink: /garden/ +pagefindIgnore: true +--- +
+ + {# ── Header ─────────────────────────────────────────────────────────── #} +
+

+ 🌱 Digital Garden +

+

+ A growing collection of ideas in various stages of development. Unlike polished blog posts, + garden notes are living documents — planted, cultivated, and sometimes transplanted as my + thinking evolves. +

+ {# Stage legend #} +
+ {% set _allStages = ["plant", "cultivate", "question", "repot", "revitalize", "revisit"] %} + {% for _s in _allStages %} + {% set _info = _s | gardenStageInfo %} + {% if _info %} + + + {{ _info.label }} + + {% endif %} + {% endfor %} +
+
+ + {# ── Posts grouped by stage ──────────────────────────────────────────── #} + {% set _stages = ["plant", "cultivate", "question", "repot", "revitalize", "revisit"] %} + + {% for _stage in _stages %} + + {# Collect posts for this stage #} + {% set _stagePosts = [] %} + {% for post in collections.gardenPosts %} + {% if post.data.gardenStage == _stage %} + {% set _stagePosts = (_stagePosts.push(post), _stagePosts) %} + {% endif %} + {% endfor %} + + {% if _stagePosts.length > 0 %} + {% set _stageInfo = _stage | gardenStageInfo %} + +
+
+

+ {{ _stageInfo.emoji }} + {{ _stageInfo.label }} +

+ + {{ _stagePosts.length }} note{% if _stagePosts.length != 1 %}s{% endif %} + +
+

{{ _stageInfo.description }}

+ + +
+ + {% endif %} + {% endfor %} + + {# ── Empty state ─────────────────────────────────────────────────────── #} + {% if not collections.gardenPosts or collections.gardenPosts.length == 0 %} +

+ The garden is being prepared. Posts with a gardenStage frontmatter property + will appear here once published. +

+ {% endif %} + +