Super-Simple Includes Documentation

v0.244.0

Advanced Step Patterns

Advanced Step Patterns: Examples 5–10

This section covers type auto-detection, HTML component libraries, structured data, step ordering, inline processing, and per-page content resolution.

Example 5: Type Auto-Detection

Sometimes you need to mix different content types in one directory. The type = "auto" setting (which is the default) detects file types by extension:

[[step]]
                emoji = "📄"
                path = "pages/"
                processing = "page"
                
                [[step]]
                emoji = "📦"
                path = "mixed-content/"
                processing = "include"
                type = "auto"  # Can be omitted — it's the default
                

With this configuration, mixed-content/ can contain:

  • banner.html → Included as HTML (no escaping)
  • article.md → Converted to HTML
  • code.txt → HTML-escaped plain text

In your template:

<header>📦banner</header>      <!-- HTML -->
                <article>📦article</article>   <!-- Markdown → HTML -->
                <pre><code>📦code</code></pre> <!-- Plain text (escaped) -->
                

When to use auto:

  • Mixed content directories
  • When you’re not sure what types you’ll need

When to use explicit types:

  • Strict validation (only accept .md files, for example)
  • Better error messages
  • Clear intent in configuration

Try it:

cd examples/05-content-types
                ssi deploy site/ output/
                

Example 6: HTML Component Libraries

Build reusable UI components with type = "html":

[[step]]
                emoji = "📎"
                path = "blocks/"
                processing = "include"
                type = "html"
                

Create components in blocks/:

<!-- blocks/alert-info.html -->
                <div class="alert alert-info">
                    <strong>Info:</strong> 💬message
                </div>
                
                <!-- blocks/card-basic.html -->
                <article class="card">
                    <h3>💬title</h3>
                    <p>💬content</p>
                </article>
                

Use in templates:

<main>
                    📎alert-info
                    📎card-basic
                    📎card-basic  <!-- Reuse as many times as needed -->
                </main>
                

Benefits:

  • Write once, use everywhere
  • Consistent UI components
  • Easy to update (change one file, affects all pages)
  • Combine with variables for dynamic content

Try it:

cd examples/06-html-blocks
                ssi deploy site/ output/
                

Example 7: Structured Data with TOML

Store site-wide variables and configuration in TOML files:

[[step]]
                emoji = "📊"
                path = "data.toml"
                processing = "include"
                type = "plain"
                options = ["inline"]
                

Your data file:

[_]
                site_name = "My Site"
                author = "Jane Doe"
                version = "2.1.0"
                contact_email = "jane@example.com"
                

In templates:

<header>
                    <h1>📊site_name</h1>
                    <p>By 📊author • Version 📊version</p>
                </header>
                <footer>
                    <p>Contact: 📊contact_email</p>
                </footer>
                

Benefits:

  • Centralized configuration
  • Easy for non-technical users to edit
  • No HTML knowledge required for content updates
  • Perfect for site-wide variables

Try it:

cd examples/07-toml-data
                ssi deploy site/ output/
                # Edit site/data.toml and regenerate to see changes
                

Example 8: Step Ordering

SSI processes steps in the order they appear in ssi-config.toml. Each step scans the full accumulated page text for its tokens and replaces them. A step has no knowledge of which earlier step introduced a token — it only sees whether the token is present in the text when it runs.

The two ordering rules

Rule 1: The page step must come first. Include steps that appear before the page step are invisible to the pipeline — their tokens remain as literal text in the output.

Rule 2: Among include steps, dependency order matters. If a block file contains a 💬 token, the HTML include step for that block must run before the plain-text include step that resolves 💬 tokens. The plain-text step scans whatever text is present when it runs — so the blocks must already be expanded.

[[step]]
                emoji = "📄"
                path = "pages/"
                processing = "page"
                
                [[step]]
                emoji = "📦"    # HTML include step — runs first among includes;
                path = "blocks/"    # block files may themselves contain 💬 tokens
                processing = "include"
                type = "html"
                
                [[step]]
                emoji = "💬"    # plain-text include step — runs after HTML step;
                path = "strings.toml"    # resolves all 💬 tokens, including those from expanded blocks
                processing = "include"
                type = "plain"
                options = ["inline"]
                

Origin is irrelevant

Once a step places content into the accumulated page text, later steps cannot tell where it came from. A 💬 token that arrived from an HTML include, a Markdown include, a TOML value, or was typed directly in the page template is treated identically by the next step. This is also why step ordering can be used to construct new token keys on the fly — see Example 24 (combining-tokens) for a demonstration of that pattern.

leftovers-okay for documentation content

Use options = ["leftovers-okay"] on include steps whose content contains token-like strings that should remain as literal text — for example, a step that includes HTML files showing SSI configuration syntax as code examples.

[[step]]
                emoji = "📁"
                path = "code-examples/"
                processing = "include"
                type = "html"
                options = ["leftovers-okay"]    # code comments contain 📦 and 💬 as display text
                

Try it:

cd examples/08-step-order
                ssi deploy site/ output/
                

Example 9: Inline vs Block Processing

Control how content is formatted with options = ["inline"]:

# Inline: newlines become spaces
                [[step]]
                emoji = "📝"
                path = "inline-text.toml"
                processing = "include"
                type = "plain"
                options = ["inline"]
                
                # Block: preserves formatting
                [[step]]
                emoji = "📃"
                path = "block-text.toml"
                processing = "include"
                type = "plain"
                

Inline behavior:

<p>This is 📝short-phrase in the middle of a sentence.</p>
                <!-- Result: "This is short text phrase in the middle of a sentence." -->
                

Block behavior:

<figure>
                    📃code-example
                </figure>
                <!-- Result: Preserves all line breaks and indentation -->
                

When to use inline:

  • Variables in sentences
  • Short text snippets
  • Navigation links
  • Metadata

When to use block:

  • Paragraphs
  • Code examples
  • Multi-line content

Try it:

cd examples/09-inline-content
                ssi deploy site/ output/
                

Example 10: Per-Page Content Resolution

The same token can resolve to different content depending on which page is being processed.

[[step]]
                emoji = "📝"
                path = "markdown-texts/"
                processing = "include"
                type = "markdown"
                

Directory structure:

markdown-texts/
                  welcome.md          # Default for all pages
                  index/
                    welcome.md        # Specific to index.html
                  about/
                    welcome.md        # Specific to about.html
                  example/
                    welcome.md        # Specific to example.html
                

All three pages use the same template:

<section class="welcome">
                    📝welcome
                </section>
                

But each gets different content:

  • index.html → Uses markdown-texts/index/welcome.md
  • about.html → Uses markdown-texts/about/welcome.md
  • example.html → Uses markdown-texts/example/welcome.md

Resolution order:

  1. Check page-specific subdirectory (markdown-texts/index/)
  2. Fall back to top-level (markdown-texts/)

Benefits:

  • Same structure, different content
  • No configuration changes to add pages
  • Easy to override specific pages
  • Shared defaults with per-page customization

Try it:

cd examples/10-page-specific
                ssi deploy site/ output/
                # Compare index.html, about.html, and example.html
                

Pattern Summary

ExamplePatternBest For
5Type auto-detectionMixed content directories
6HTML componentsReusable UI widgets
7TOML dataSite-wide variables
8Step orderingConfiguring the pipeline correctly
9Inline processingMid-sentence variables
10Per-page resolutionPage-specific content

Combining Patterns

These patterns work well together:

# Pages
                [[step]]
                emoji = "📄"
                path = "pages/"
                processing = "page"
                
                # Reusable components
                [[step]]
                emoji = "📎"
                path = "blocks/"
                processing = "include"
                type = "html"
                
                # Site-wide variables
                [[step]]
                emoji = "💬"
                path = "strings.toml"
                processing = "include"
                type = "plain"
                options = ["inline"]
                
                # Per-page content
                [[step]]
                emoji = "📝"
                path = "markdown-texts/"
                processing = "include"
                type = "markdown"
                

This gives you reusable HTML components (📎), site-wide variables (💬), and per-page content (📝) in one site.

Processing Order Strategy

Understanding how SSI processes include sources in order helps you make strategic decisions about configuration.

How Sequential Processing Works

Include sources process sequentially, with each source scanning the output from all previous sources:

Template:          <div>📎widget 💬title</div>
                After source 1 (📎): <div><h1>Header</h1> 💬title</div>
                After source 2 (💬): <div><h1>Header</h1> My Site</div>
                

Each step scans the accumulated result, not just the original template.

Forward-Only Processing

Because processing moves forward through sources:

  • Earlier sources can use tokens from later sources (they haven’t been expanded yet)
  • Later sources scan content inserted by earlier sources (it’s already in the template)
  • The last source’s content is not scanned again (no more steps)

Strategic Ordering: Preventing Token Expansion

Place sources containing token-like patterns last in your configuration to prevent unwanted expansion.

Example: Including third-party HTML that happens to contain emoji followed by text:

[[step]]
                emoji = "📎"
                path = "blocks/"
                processing = "include"
                type = "html"
                
                [[step]]
                emoji = "💬"
                path = "config.toml"
                processing = "include"
                type = "plain"
                
                [[step]]  # Place last — content won't be scanned for 📎 or 💬
                emoji = "🎨"
                path = "third-party-widgets/"
                processing = "include"
                type = "html"
                

If a file in third-party-widgets/ contains 📎something in its HTML:

  • Placed first: Would be expanded if blocks/ contains a matching file
  • Placed last: Stays as literal text 📎something

Other uses for last-position sources:

  • User-generated content you don’t control
  • Code examples showing SSI syntax
  • Raw HTML from external sources

Dependency Ordering

For sources that should interact, order them by dependency:

[[step]]  # Base layer — defines fundamental variables
                emoji = "🔧"
                path = "config.toml"
                
                [[step]]  # Middle layer — can use 🔧 tokens
                emoji = "📎"
                path = "blocks/"
                
                [[step]]  # Top layer — can use 🔧 and 📎 tokens
                emoji = "📝"
                path = "content/"
                

This creates a natural hierarchy: config → components → content.