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:
@@ -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 #}
|
||||||
{% for section in homepageConfig.sections %}
|
{% if layout == "single-column" %}
|
||||||
{% if section.type == "hero" %}
|
|
||||||
{# Hero is handled above #}
|
{# Single column — no sidebar, full width sections #}
|
||||||
{% elif section.type == "recent-posts" %}
|
<div class="homepage-sections">
|
||||||
{% include "components/sections/recent-posts.njk" %}
|
{% for section in homepageConfig.sections %}
|
||||||
{% elif section.type == "custom-html" %}
|
{% if section.type != "hero" %}
|
||||||
{% include "components/sections/custom-html.njk" %}
|
{% include "components/homepage-section.njk" %}
|
||||||
{% elif section.type == "cv-experience" %}
|
{% endif %}
|
||||||
{% include "components/sections/cv-experience.njk" ignore missing %}
|
{% endfor %}
|
||||||
{% elif section.type == "cv-projects" %}
|
</div>
|
||||||
{% include "components/sections/cv-projects.njk" ignore missing %}
|
|
||||||
{% elif section.type == "cv-skills" %}
|
{% elif layout == "two-column" and hasSidebar %}
|
||||||
{% include "components/sections/cv-skills.njk" ignore missing %}
|
|
||||||
{% elif section.type == "cv-education" %}
|
{# Two column — sections + sidebar #}
|
||||||
{% include "components/sections/cv-education.njk" ignore missing %}
|
<div class="layout-with-sidebar">
|
||||||
{% elif section.type == "cv-interests" %}
|
<div class="main-content">
|
||||||
{% include "components/sections/cv-interests.njk" ignore missing %}
|
<div class="homepage-sections">
|
||||||
{% elif section.type == "blogroll" %}
|
{% for section in homepageConfig.sections %}
|
||||||
{% include "components/sections/blogroll.njk" ignore missing %}
|
{% if section.type != "hero" %}
|
||||||
{% elif section.type == "podroll" %}
|
{% include "components/homepage-section.njk" %}
|
||||||
{% include "components/sections/podroll.njk" ignore missing %}
|
{% endif %}
|
||||||
{% elif section.type == "github-activity" %}
|
{% endfor %}
|
||||||
{% include "components/sections/github-activity.njk" ignore missing %}
|
</div>
|
||||||
{% elif section.type == "youtube" %}
|
</div>
|
||||||
{% include "components/sections/youtube.njk" ignore missing %}
|
<aside class="sidebar" data-pagefind-ignore>
|
||||||
{% elif section.type == "funkwhale" %}
|
{% include "components/homepage-sidebar.njk" %}
|
||||||
{% include "components/sections/funkwhale.njk" ignore missing %}
|
</aside>
|
||||||
{% elif section.type == "lastfm" %}
|
</div>
|
||||||
{% include "components/sections/lastfm.njk" ignore missing %}
|
|
||||||
{% else %}
|
{% elif layout == "full-width-hero" %}
|
||||||
{# Unknown section type - log warning #}
|
|
||||||
<!-- Unknown section type: {{ section.type }} -->
|
{# Full width hero (already rendered above), then two-column below #}
|
||||||
{% endif %}
|
{% if hasSidebar %}
|
||||||
{% endfor %}
|
<div class="layout-with-sidebar">
|
||||||
</div>
|
<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 %}
|
||||||
|
|||||||
@@ -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 %}
|
||||||
@@ -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 %}
|
||||||
@@ -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">
|
||||||
|
|||||||
Reference in New Issue
Block a user