feat: wire homepage builder layout system and sidebar control

- base.njk: skip hardcoded sidebar when homepage builder is active
- homepage-builder.njk: implement 3 layouts (single-column, two-column,
  full-width-hero) with CSS grid and sidebar rendering
- homepage-section.njk: section type dispatcher (extracted for reuse)
- homepage-sidebar.njk: maps widget types to existing widget partials

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Ricardo
2026-02-08 19:08:27 +01:00
parent b8c60b1a81
commit b4bc2f6f07
4 changed files with 138 additions and 39 deletions
+73 -35
View File
@@ -1,45 +1,83 @@
{# {#
Homepage Builder - renders configured sections from homepageConfig Homepage Builder - renders configured layout, sections, and sidebar
Used when indiekit-endpoint-homepage plugin is installed and configured from homepageConfig (written by indiekit-endpoint-homepage plugin)
#} #}
{% set layout = homepageConfig.layout or "two-column" %}
{% set hasSidebar = homepageConfig.sidebar and homepageConfig.sidebar.length %}
{# Hero — rendered before layout wrapper when enabled #}
{% if homepageConfig.hero and homepageConfig.hero.enabled %} {% if homepageConfig.hero and homepageConfig.hero.enabled %}
{% include "components/sections/hero.njk" %} {% include "components/sections/hero.njk" %}
{% endif %} {% endif %}
<div class="homepage-sections"> {# Layout wrapper #}
{% if layout == "single-column" %}
{# Single column — no sidebar, full width sections #}
<div class="homepage-sections">
{% for section in homepageConfig.sections %} {% for section in homepageConfig.sections %}
{% if section.type == "hero" %} {% if section.type != "hero" %}
{# Hero is handled above #} {% include "components/homepage-section.njk" %}
{% 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 == "cv-education" %}
{% include "components/sections/cv-education.njk" ignore missing %}
{% elif section.type == "cv-interests" %}
{% include "components/sections/cv-interests.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 #}
<!-- Unknown section type: {{ section.type }} -->
{% endif %} {% endif %}
{% endfor %} {% endfor %}
</div> </div>
{% elif layout == "two-column" and hasSidebar %}
{# Two column — sections + sidebar #}
<div class="layout-with-sidebar">
<div class="main-content">
<div class="homepage-sections">
{% for section in homepageConfig.sections %}
{% if section.type != "hero" %}
{% include "components/homepage-section.njk" %}
{% endif %}
{% endfor %}
</div>
</div>
<aside class="sidebar" data-pagefind-ignore>
{% include "components/homepage-sidebar.njk" %}
</aside>
</div>
{% elif layout == "full-width-hero" %}
{# Full width hero (already rendered above), then two-column below #}
{% if hasSidebar %}
<div class="layout-with-sidebar">
<div class="main-content">
<div class="homepage-sections">
{% for section in homepageConfig.sections %}
{% if section.type != "hero" %}
{% include "components/homepage-section.njk" %}
{% endif %}
{% endfor %}
</div>
</div>
<aside class="sidebar" data-pagefind-ignore>
{% include "components/homepage-sidebar.njk" %}
</aside>
</div>
{% else %}
<div class="homepage-sections">
{% for section in homepageConfig.sections %}
{% if section.type != "hero" %}
{% include "components/homepage-section.njk" %}
{% endif %}
{% endfor %}
</div>
{% endif %}
{% else %}
{# Fallback — two-column without sidebar, or unknown layout #}
<div class="homepage-sections">
{% for section in homepageConfig.sections %}
{% if section.type != "hero" %}
{% include "components/homepage-section.njk" %}
{% endif %}
{% endfor %}
</div>
{% endif %}
+30
View File
@@ -0,0 +1,30 @@
{# Homepage Section Dispatcher — maps section.type to the right partial #}
{% if 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 == "cv-education" %}
{% include "components/sections/cv-education.njk" ignore missing %}
{% elif section.type == "cv-interests" %}
{% include "components/sections/cv-interests.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: {{ section.type }} -->
{% endif %}
+28
View File
@@ -0,0 +1,28 @@
{# Homepage Builder Sidebar — renders widgets from homepageConfig.sidebar #}
{% if homepageConfig.sidebar and homepageConfig.sidebar.length %}
{% for widget in homepageConfig.sidebar %}
{% if widget.type == "author-card" %}
{% include "components/widgets/author-card.njk" %}
{% elif widget.type == "social-activity" %}
{% include "components/widgets/social-activity.njk" %}
{% elif widget.type == "github-repos" %}
{% include "components/widgets/github-repos.njk" %}
{% elif widget.type == "funkwhale" %}
{% include "components/widgets/funkwhale.njk" %}
{% elif widget.type == "recent-posts" %}
{% include "components/widgets/recent-posts.njk" %}
{% elif widget.type == "blogroll" %}
{% include "components/widgets/blogroll.njk" %}
{% elif widget.type == "categories" %}
{% include "components/widgets/categories.njk" %}
{% elif widget.type == "search" %}
{# Pagefind search widget #}
<div class="sidebar-widget">
<h3 class="text-sm font-semibold text-surface-600 dark:text-surface-400 uppercase tracking-wide mb-3">Search</h3>
<div id="search"></div>
</div>
{% else %}
<!-- Unknown widget type: {{ widget.type }} -->
{% endif %}
{% endfor %}
{% endif %}
+4 -1
View File
@@ -270,7 +270,7 @@
</header> </header>
<main class="container py-8" data-pagefind-body> <main class="container py-8" data-pagefind-body>
{% if withSidebar %} {% if withSidebar and not (homepageConfig and homepageConfig.sections) %}
<div class="layout-with-sidebar"> <div class="layout-with-sidebar">
<div class="main-content"> <div class="main-content">
{{ content | safe }} {{ content | safe }}
@@ -279,6 +279,9 @@
{% include "components/sidebar.njk" %} {% include "components/sidebar.njk" %}
</aside> </aside>
</div> </div>
{% elif withSidebar and homepageConfig and homepageConfig.sections %}
{# Homepage builder controls its own layout and sidebar #}
{{ content | safe }}
{% elif withBlogSidebar %} {% elif withBlogSidebar %}
<div class="layout-with-sidebar"> <div class="layout-with-sidebar">
<div class="main-content"> <div class="main-content">