Skip to content

Advanced Template Patterns

Advanced techniques for building sophisticated, data-driven templates.

Conditional Template Loading

Load different partials based on context:

html
<!-- Load section-specific sidebars -->
{{ if eq .Section.Name "blog" }}
    {{ template "partials/_blog_sidebar.html" . }}
{{ else if eq .Section.Name "notes" }}  
    {{ template "partials/_notes_sidebar.html" . }}
{{ else }}
    {{ template "partials/_default_sidebar.html" . }}
{{ end }}

<!-- Feature flags from config -->
{{ if .Site.Config.extra.enable_comments }}
    {{ template "partials/_comments.html" . }}
{{ end }}

{{ if .Site.Config.extra.enable_analytics }}
    {{ template "partials/_analytics.html" . }}
{{ end }}

Complex Data Processing

Filtering and Transforming Collections

html
<!-- Get published, featured posts from last 30 days -->
{{ $posts := get_section "blog" }}
{{ $published := where $posts.Children "Config.draft" false }}
{{ $featured := where $published "Config.featured" true }}
{{ $recent := first 5 (reverse (where $published "Config.draft" false)) }}

<section class="featured">
    <h2>Featured Posts</h2>
    {{ range $featured }}
        <article>
            <h3><a href="{{ .Permalink }}">{{ .Config.title }}</a></h3>
            <p>{{ .Config.description }}</p>
        </article>
    {{ end }}
</section>

<section class="recent">
    <h2>Recent Posts</h2>
    {{ range $recent }}
        <article>
            <h3><a href="{{ .Permalink }}">{{ .Config.title }}</a></h3>
            <time>{{ date .Config.date "Jan 2" }}</time>
        </article>
    {{ end }}
</section>

Grouping and Aggregation

html
<!-- Group posts by year -->
{{ $posts := .Section.Children }}
{{ $groups := group_by $posts "Config.date.Year" }}

{{ range $groups }}
    <section class="year-{{ .Key }}">
        <h2>{{ .Key }}</h2>
        {{ range .Items }}
            <article>
                <time>{{ date .Config.date "Jan 2" }}</time>
                <a href="{{ .Permalink }}">{{ .Config.title }}</a>
            </article>
        {{ end }}
    </section>
{{ end }}

Multi-Level Filtering

html
<!-- Complex query: published blog posts tagged "golang", sorted by date -->
{{ $blog := get_section "blog" }}
{{ $published := where $blog.Children "Config.draft" false }}
{{ $goPosts := where $published "Config.tags" "golang" }}
{{ $sorted := sort $goPosts ".Config.date" "desc" }}

<div class="golang-posts">
    <h2>Go Programming Posts</h2>
    {{ range $sorted }}
        <article>
            <h3><a href="{{ .Permalink }}">{{ .Config.title }}</a></h3>
            <time>{{ date .Config.date "January 2, 2006" }}</time>
        </article>
    {{ end }}
</div>

Dynamic Content Assembly

Building Navigation Dynamically

html
<!-- Generate navigation from sections -->
<nav class="main-nav">
    {{ $sections := slice "blog" "notes" "projects" }}
    {{ range $sections }}
        {{ $section := get_section . }}
        <a href="/{{ . }}/" class="{{ if eq $.Page.Section . }}active{{ end }}">
            {{ $section.Config.title }}
            <span class="count">({{ len $section.Children }})</span>
        </a>
    {{ end }}
</nav>
html
<!-- Find related posts by tags -->
{{ $currentTags := .Page.Config.tags }}
{{ $blog := get_section "blog" }}
{{ $related := slice }}

{{ range $blog.Children }}
    {{ if ne .Permalink $.Page.Permalink }}
        {{ range .Config.tags }}
            {{ if contains $currentTags . }}
                {{ $related = $related | append $ }}
            {{ end }}
        {{ end }}
    {{ end }}
{{ end }}

{{ if gt (len $related) 0 }}
    <aside class="related-posts">
        <h3>Related Posts</h3>
        {{ range first 3 $related }}
            <article>
                <a href="{{ .Permalink }}">{{ .Config.title }}</a>
            </article>
        {{ end }}
    </aside>
{{ end }}

Performance Optimization

Caching Expensive Operations

html
<!-- Cache section data in variable -->
{{ $blog := get_section "blog" }}
{{ $notes := get_section "notes" }}

<!-- Reuse without re-fetching -->
<p>{{ len $blog.Children }} blog posts</p>
<p>{{ len $notes.Children }} notes</p>

{{ range first 5 (reverse $blog.Children) }}
    <!-- Use cached data -->
{{ end }}

Lazy Loading Content

html
<!-- Load related content only if needed -->
{{ if .Page.Config.extra.show_related }}
    {{ $related := where .Section.Children "Config.tags" .Page.Config.tags }}
    {{ range first 3 $related }}
        <article>{{ .Config.title }}</article>
    {{ end }}
{{ end }}

Advanced Templating Techniques

Template Composition

html
<!-- Build complex layouts from smaller pieces -->
<div class="page-layout">
    <aside class="sidebar">
        {{ template "partials/_sidebar_about.html" . }}
        {{ template "partials/_sidebar_tags.html" . }}
        {{ template "partials/_sidebar_recent.html" . }}
    </aside>
    
    <main class="content">
        {{ block "content" . }}{{ end }}
    </main>
    
    <aside class="widgets">
        {{ template "partials/_widget_newsletter.html" . }}
        {{ template "partials/_widget_popular.html" . }}
    </aside>
</div>

Recursive Templates

html
<!-- Render nested comment threads -->
<!-- macros/comment_thread.html -->
<div class="comment" data-id="{{ .id }}">
    <div class="comment-body">
        <strong>{{ .author }}</strong>
        <p>{{ .text }}</p>
    </div>
    
    {{ if .replies }}
        <div class="comment-replies">
            {{ range .replies }}
                {{ template "macros/comment_thread.html" . }}
            {{ end }}
        </div>
    {{ end }}
</div>

Template Middleware Pattern

html
<!-- Wrap content with common elements -->
{{ define "with_sidebar" }}
    <div class="layout-with-sidebar">
        <main>{{ .content }}</main>
        <aside>{{ .sidebar }}</aside>
    </div>
{{ end }}

<!-- Usage -->
{{ template "with_sidebar" (dict 
    "content" .Page.Content 
    "sidebar" "Sidebar content here"
) }}

State Management

Maintaining State Across Templates

html
<!-- Build state object -->
{{ $state := dict 
    "page" .Page 
    "site" .Site 
    "showTOC" .Page.Config.extra.toc
    "theme" (priority .Page.Config.extra.theme .Site.Config.extra.theme "light")
}}

<!-- Pass state to partials -->
{{ template "partials/_article.html" $state }}

Context Preservation

html
<!-- Preserve parent context in loops -->
{{ range .Section.Children }}
    <!-- $ refers to root context -->
    <article>
        <h2>{{ .Config.title }}</h2>
        <p>Site: {{ $.Site.Config.title }}</p>
        <p>Current section: {{ $.Section.Name }}</p>
    </article>
{{ end }}

Error Handling

Graceful Degradation

html
<!-- Handle missing data gracefully -->
{{ with .Page.Config.extra.author }}
    <p>By {{ . }}</p>
{{ else }}
    <p>By {{ .Site.Config.extra.name }}</p>
{{ end }}

<!-- Provide fallback images -->
{{ $image := priority .Page.Config.img .Section.Config.img "/img/default.jpg" }}
<img src="{{ $image }}" alt="{{ .Page.Config.title }}">

Validation

html
<!-- Validate required data -->
{{ if and .Page.Config.title .Page.Content }}
    <article>
        <h1>{{ .Page.Config.title }}</h1>
        {{ .Page.Content }}
    </article>
{{ else }}
    <div class="error">
        <p>Missing required page data</p>
    </div>
{{ end }}

Debugging Patterns

Development Mode Features

html
{{ if eq .Site.Environment "development" }}
    <div id="debug-toolbar">
        <h3>Debug Info</h3>
        <dl>
            <dt>Template:</dt>
            <dd>{{ .TemplateName }}</dd>
            
            <dt>Section:</dt>
            <dd>{{ .Section.Name }}</dd>
            
            <dt>Page Type:</dt>
            <dd>{{ .Page.Type }}</dd>
        </dl>
        
        <details>
            <summary>Full Page Data</summary>
            <pre>{{ .Page | json }}</pre>
        </details>
    </div>
{{ end }}

Performance Monitoring

html
<!-- Track template rendering time -->
{{ $start := now }}

<!-- Complex template logic -->
{{ range .Section.Children }}
    <!-- ... -->
{{ end }}

{{ $duration := sub (now) $start }}
{{ if eq .Site.Environment "development" }}
    <p>Rendered in {{ $duration }}ms</p>
{{ end }}

Advanced Use Cases

Multi-Language Support

html
<!-- Language-aware content -->
{{ $lang := priority .Page.Config.lang .Site.Config.lang "en" }}

<html lang="{{ $lang }}">
    <head>
        {{ if eq $lang "en" }}
            <title>{{ .Page.Config.title }}</title>
        {{ else if eq $lang "fr" }}
            <title>{{ .Page.Config.title_fr }}</title>
        {{ end }}
    </head>
</html>

A/B Testing

html
<!-- Conditional variants -->
{{ $variant := .Site.Config.extra.ab_variant | default "A" }}

{{ if eq $variant "A" }}
    <div class="hero-variant-a">
        <h1>Welcome to Gozzi</h1>
    </div>
{{ else }}
    <div class="hero-variant-b">
        <h1>Build Fast Static Sites</h1>
    </div>
{{ end }}

Dynamic Schema Generation

html
<!-- Generate JSON-LD schema -->
<script type="application/ld+json">
{
    "@context": "https://schema.org",
    "@type": "BlogPosting",
    "headline": "{{ .Page.Config.title }}",
    "datePublished": "{{ .Page.Config.date.Format "2006-01-02" }}",
    "author": {
        "@type": "Person",
        "name": "{{ .Site.Config.extra.name }}"
    }
    {{ if .Page.Config.img }},
    "image": "{{ .Page.Config.img_url }}"
    {{ end }}
}
</script>

Related:

Released under the MIT License.