FaceFlow Variables — Reusable Template Fragments

Variables are the dynamic building blocks of FaceFlow. They allow you to create reusable template snippets — HTML, CSS, and JavaScript — that can be embedded anywhere in your pages, layouts, and components. Variables use the powerful Facet template engine to render dynamic content with a Handlebars-like syntax.

Variable Developer Docs

Variables are reusable template-driven fragments rendered within FaceFlow-managed contexts.

For technical users, Variables are one of the lightest reuse primitives in FaceFlow. They are appropriate when output should be shared across layouts, components, lists, or other render surfaces without introducing a full Component schema.

Core Responsibility

A Variable is responsible for:

  • reusable template output
  • optional CSS and client-side behavior
  • simple parameterization through attributes
  • context-aware rendering
  • cache-aware delivery for repeated output

Use a Variable when the reuse unit is smaller than a Component but more durable than copied markup.

Variable Model

A typical Variable includes:

  • a stable identity
  • a Facet template
  • optional CSS
  • optional JavaScript
  • optional attributes
  • category and description metadata
  • a cache mode

Conceptually:

{
  "name": "copyright-notice",
  "title": "Copyright Notice",
  "category": "footer",
  "cacheMode": "auto",
  "attributes": [
    { "name": "company", "default": "PageFace" }
  ],
  "html": "<p>&copy; {{ now.year }} {{ attr.company }}</p>",
  "css": ".copyright { color: #64748b; }",
  "js": ""
}

The exact storage implementation is internal. The contract above is the important part for technical authors.

Embedding Syntax

Variables are embedded with the double-bracket syntax:

[[copyright-notice]]

With attributes:

[[copyright-notice company="Acme Inc"]]

Variables can also be embedded inside other templates:

<footer class="site-footer">
  [[copyright-notice company="Acme Inc"]]
</footer>

Attribute values should be passed as quoted literals in the embed syntax.

If a Variable needs page-aware or runtime-aware behavior, read from the rendering context inside the Variable template instead of trying to inject an unquoted expression into the attribute list.

Attribute Model

Attributes are named inputs passed to the Variable at render time.

They are appropriate for:

  • copy variants
  • labels
  • simple visual options
  • small business-specific values

Example:

[[cta-badge label="New" tone="accent"]]

Template usage:

<span class="badge badge-{{ attr.tone | default('neutral') }}">
  {{ attr.label }}
</span>

Attributes should stay lightweight. If the reuse unit needs a large editable schema, that usually indicates a Component instead.

Example of mixing literal attributes with runtime context safely:

<span class="badge badge-{{ attr.tone | default('neutral') }}">
  {{ attr.label | default(page.title) }}
</span>

Rendering Context

Variables can render against a wider runtime context. Common context objects include:

  • page
  • user
  • pages
  • site
  • languages / lang
  • now
  • attr

Example:

<p class="eyebrow">
  {{ page.title }} updated {{ now.year }}
</p>

Or a query-driven example:

<ul class="recent-posts">
  {{#pages selector="template=blog-post, sort=-published, limit=3" as="item"}}
    <li><a href="{{ item.url }}">{{ item.title }}</a></li>
  {{/pages}}
</ul>

This is what makes Variables useful for small dynamic fragments without requiring a full List or Component.

Supported Placement

Variables are commonly used in:

  • Layout templates
  • Component templates
  • List templates
  • other Variables
  • supported content surfaces that pass through FaceFlow rendering

Typical examples:

[[site-announcement]]
[[page-breadcrumbs]]
[[recent-posts title="From the blog"]]

Nesting

Variables can reference other Variables:

<div class="footer-meta">
  [[social-links]]
  [[copyright-notice company="PageFace"]]
</div>

Nesting is useful when it improves clarity. Avoid deep chains that make debugging or change impact hard to reason about.

Cache Modes

Variables support multiple cache strategies.

Auto

Use for most cases. The runtime determines whether static or dynamic behavior is appropriate based on rendering needs.

Static

Use when the output does not depend on changing user, time, or request-sensitive context.

Dynamic

Use when the output depends on frequently changing context and should not behave like a fully cache-friendly fragment.

Example decision rule:

current year footer -> auto
simple shared legal text -> static
logged-in user greeting -> dynamic

Performance Guidance

Variables are often reused widely, so performance discipline matters.

  • prefer auto or static unless there is a real reason for dynamic
  • avoid expensive query-heavy output in fragments used across many pages
  • treat widely shared Variables as performance-sensitive assets
  • review change impact before editing a heavily reused Variable

Preview and Testing

When testing a Variable, review:

  • rendering with realistic attributes
  • behavior inside the actual page or component context
  • output under the intended cache mode
  • nested Variable behavior if composition is involved

Example test pattern:

[[cta-badge label="Launch Ready" tone="success"]]
[[cta-badge label="New" tone="accent"]]

When To Use a Variable

Use a Variable when:

  • the fragment is reused in several places
  • the structure is small and stable
  • the inputs are limited
  • the output needs context awareness

Do not use a Variable when:

  • the content is unique to one Page
  • a full editable schema is required
  • the structure is large enough to be a reusable section
  • the output is really a dynamic archive rather than a fragment

Anti-Patterns

Avoid:

  • turning Variables into mini-pages
  • hiding large business workflows inside one Variable
  • adding too many attributes to simulate a Component schema
  • deeply nested Variable chains with unclear ownership
  • using dynamic cache mode by default without a real need

Example Build Patterns

Small utility fragment:

[[copyright-notice company="PageFace"]]

Page-aware reusable snippet:

<aside class="page-summary">
  <h3>{{ page.title }}</h3>
  <p>{{ page.summary }}</p>
</aside>

Query-driven widget:

<div class="resource-count">
  {{ pages.count selector="template=resource-item" }} resources
</div>