From d9e99fa9ccab6b405fe0fde076a34c092d1ad7f4 Mon Sep 17 00:00:00 2001 From: Ricardo Date: Sun, 8 Feb 2026 15:55:08 +0100 Subject: [PATCH] feat: add homepage builder components for Phase 3 - homepage-builder.njk: master section renderer for configured sections - sections/hero.njk: hero section with avatar, name, title, bio, social - sections/recent-posts.njk: configurable recent posts section - sections/custom-html.njk: freeform HTML content block - Wire home.njk Tier 1 to include homepage-builder when config exists Part of indiekit-endpoint-homepage plugin integration. Co-Authored-By: Claude Opus 4.5 --- _includes/components/homepage-builder.njk | 41 ++++++++++++ _includes/components/sections/custom-html.njk | 18 +++++ _includes/components/sections/hero.njk | 66 +++++++++++++++++++ .../components/sections/recent-posts.njk | 54 +++++++++++++++ _includes/layouts/home.njk | 7 +- 5 files changed, 181 insertions(+), 5 deletions(-) create mode 100644 _includes/components/homepage-builder.njk create mode 100644 _includes/components/sections/custom-html.njk create mode 100644 _includes/components/sections/hero.njk create mode 100644 _includes/components/sections/recent-posts.njk diff --git a/_includes/components/homepage-builder.njk b/_includes/components/homepage-builder.njk new file mode 100644 index 0000000..cd2e30b --- /dev/null +++ b/_includes/components/homepage-builder.njk @@ -0,0 +1,41 @@ +{# + Homepage Builder - renders configured sections from homepageConfig + Used when indiekit-endpoint-homepage plugin is installed and configured +#} + +{% if homepageConfig.hero and homepageConfig.hero.enabled %} + {% include "components/sections/hero.njk" %} +{% endif %} + +
+ {% for section in homepageConfig.sections %} + {% if section.type == "hero" %} + {# Hero is handled above #} + {% elif section.type == "recent-posts" %} + {% include "components/sections/recent-posts.njk" %} + {% elif section.type == "custom-html" %} + {% include "components/sections/custom-html.njk" %} + {% elif section.type == "cv-experience" %} + {% include "components/sections/cv-experience.njk" ignore missing %} + {% elif section.type == "cv-projects" %} + {% include "components/sections/cv-projects.njk" ignore missing %} + {% elif section.type == "cv-skills" %} + {% include "components/sections/cv-skills.njk" ignore missing %} + {% elif section.type == "blogroll" %} + {% include "components/sections/blogroll.njk" ignore missing %} + {% elif section.type == "podroll" %} + {% include "components/sections/podroll.njk" ignore missing %} + {% elif section.type == "github-activity" %} + {% include "components/sections/github-activity.njk" ignore missing %} + {% elif section.type == "youtube" %} + {% include "components/sections/youtube.njk" ignore missing %} + {% elif section.type == "funkwhale" %} + {% include "components/sections/funkwhale.njk" ignore missing %} + {% elif section.type == "lastfm" %} + {% include "components/sections/lastfm.njk" ignore missing %} + {% else %} + {# Unknown section type - log warning #} + + {% endif %} + {% endfor %} +
diff --git a/_includes/components/sections/custom-html.njk b/_includes/components/sections/custom-html.njk new file mode 100644 index 0000000..5045160 --- /dev/null +++ b/_includes/components/sections/custom-html.njk @@ -0,0 +1,18 @@ +{# + Custom HTML Section - freeform HTML/markdown content block + Rendered by homepage-builder when custom-html section is configured +#} + +{% set sectionConfig = section.config or {} %} + +
+ {% if sectionConfig.title %} +

+ {{ sectionConfig.title }} +

+ {% endif %} + +
+ {{ sectionConfig.content | safe }} +
+
diff --git a/_includes/components/sections/hero.njk b/_includes/components/sections/hero.njk new file mode 100644 index 0000000..253cc62 --- /dev/null +++ b/_includes/components/sections/hero.njk @@ -0,0 +1,66 @@ +{# + Hero Section - author intro with avatar, name, title, bio + Rendered by homepage-builder when hero is enabled +#} + +{% set heroConfig = homepageConfig.hero or {} %} + +
+
+ {# Avatar #} + {% if heroConfig.showAvatar != false %} + {{ site.author.name }} + {% endif %} + + {# Introduction #} +
+

+ {{ site.author.name }} +

+

+ {{ site.author.title }} +

+ {% if site.author.bio %} +

+ {{ site.author.bio }} +

+ {% endif %} + {% if site.description %} +

+ {{ site.description }} + Read more → +

+ {% endif %} + + {# Social Links #} + {% if heroConfig.showSocial != false and site.social %} + + {% endif %} +
+
+
diff --git a/_includes/components/sections/recent-posts.njk b/_includes/components/sections/recent-posts.njk new file mode 100644 index 0000000..f4449a0 --- /dev/null +++ b/_includes/components/sections/recent-posts.njk @@ -0,0 +1,54 @@ +{# + Recent Posts Section - displays latest posts from any collection + Rendered by homepage-builder when recent-posts section is configured +#} + +{% set sectionConfig = section.config or {} %} +{% set maxItems = sectionConfig.maxItems or 5 %} +{% set showSummary = sectionConfig.showSummary if sectionConfig.showSummary is defined else true %} + +{% if collections.posts and collections.posts.length %} +
+

+ {{ sectionConfig.title or "Recent Posts" }} +

+ +
+ {% for post in collections.posts | head(maxItems) %} +
+

+ + {{ post.data.title or post.data.name or "Untitled" }} + +

+ + {% if showSummary and post.data.summary %} +

+ {{ post.data.summary }} +

+ {% endif %} + +
+ + {% if post.data.postType %} + + {{ post.data.postType }} + + {% endif %} +
+
+ {% endfor %} +
+ + {% if sectionConfig.showViewAll != false %} + + {{ sectionConfig.viewAllText or "View all posts" }} + + + + + {% endif %} +
+{% endif %} diff --git a/_includes/layouts/home.njk b/_includes/layouts/home.njk index e0237e7..e3802da 100644 --- a/_includes/layouts/home.njk +++ b/_includes/layouts/home.njk @@ -69,12 +69,9 @@ withSidebar: true (cv.projects and cv.projects.length) or (cv.skills and (cv.skills | dictsort | length)) %} -{# --- Tier 1: Plugin-driven layout (future) --- #} +{# --- Tier 1: Plugin-driven layout --- #} {% if homepageConfig and homepageConfig.sections %} -{# Reserved for indiekit-endpoint-homepage plugin — will render configured sections here #} -
-

Homepage plugin layout will render here.

-
+ {% include "components/homepage-builder.njk" %} {# --- Tier 2: CV-based layout --- #} {% elif hasCvData %}