Facet Reference
Facet Reference
Use this page when the primary syntax guide is no longer enough and you need deeper reference material for Facet behavior, context objects, helper contracts, and rendering rules.
This page is intentionally dense. It is the technical reference companion to:
What This Page Covers
Use this reference when you need details about:
- context objects and their common properties
- page, media, and collection access patterns
- image and map helper contracts
- filters by category
- Variable system behavior
- layout-level slots
- managed data attributes
- media references
- rendering and security rules
Context Objects
Facet templates have access to a controlled set of root-level objects. Which properties are useful depends on the current render surface, but the same mental model applies everywhere.
page
page is the current page object in the current render context.
Core Page Properties
Common scalar properties include:
page.idpage.namepage.titlepage.urlpage.httpUrlpage.pathpage.templatepage.createdpage.modifiedpage.createdStrpage.modifiedStrpage.statuspage.sortpage.numChildren
Typical usage:
<h1>{{ page.title }}</h1>
<p>Updated {{ page.modified | date("F j, Y") }}</p>Status-style Properties
Common boolean-style properties include:
page.isPublishedpage.isHiddenpage.isUnpublishedpage.isTrashpage.isNewpage.hasChildrenpage.isEditable
Example:
{{#if page.hasChildren}}
<p>This page has child pages.</p>
{{/if}}page.isEditable is especially useful for UI that should only appear to editors of the current page:
{{#if page.isEditable}}
<a href="{{ page.url }}?edit=1">Edit this page</a>
{{/if}}Relational Properties
Facet commonly exposes relational access like:
page.parentpage.parentspage.rootParentpage.childrenpage.siblingspage.nextpage.prevpage.find
Examples:
{{ page.parent.title }}
{{ page.rootParent.title }}
{{#each page.children as="child"}}
<a href="{{ child.url }}">{{ child.title }}</a>
{{/each}}Media Properties
Common media-oriented properties include:
page.imagespage.imagepage.files
Examples:
{{#each page.images as="img"}}
<img src="{{ img.width(800).webp.url }}" alt="{{ img.description }}">
{{/each}}
{{#each page.files as="file"}}
<a href="{{ file.url }}">{{ file.filename }}</a>
{{/each}}Image Object Properties
Typical image object properties include:
img.urlimg.httpUrlimg.filenameimg.descriptionimg.widthimg.heightimg.extimg.filesizeimg.webp.urlimg.raw.url
File Object Properties
Typical file object properties include:
file.urlfile.httpUrlfile.filenamefile.descriptionfile.extfile.filesize
Image Transforms
Page and query image objects support chained transforms:
{{ page.image.width(800) }}
{{ page.image.size(600, 400) }}
{{ page.image.size(600, 400).webp.url }}
{{ page.image.raw.url }}In loops:
{{#each page.images as="img"}}
<img src="{{ img.size(400, 300).webp.url }}" alt="{{ img.description }}">
{{/each}}Collection Methods
Common collection helpers include:
firstlastcounteq(n)slice(start, length)
Examples:
{{ page.images.first.url }}
{{ page.images.count }}
{{ page.images.eq(2).url }}Dynamic Field Access
Custom page fields can be accessed by name:
{{ page.summary }}
{{ page.body }}
{{ page.headline }}
{{ page.field name="my_custom_field" }}Use this when the current render surface really depends on page-level data. Do not use it to hide a weak Component field contract.
Localized URL
Facet may expose localized URL helpers for page-aware multilingual rendering:
{{ page.localUrl lang="fr" }}
{{ page.localUrl lang="default" }}user
user represents the current user context.
Common properties include:
user.iduser.nameuser.titleuser.emailuser.displayNameuser.isLoggedinuser.isGuestuser.isSuperuseruser.language
Typical usage:
{{#if user.isLoggedin}}
<span>Hello, {{ user.displayName }}!</span>
{{else}}
<a href="/login/">Log In</a>
{{/if}}pages
pages exposes query-oriented helpers for scalar or aggregate outputs.
Common patterns include:
pages.count selector="..."pages.first selector="..."pages.last selector="..."pages.titles selector="..." sep=", "pages.json selector="..."
Examples:
<p>Total posts: {{ pages.count selector="template=blog-post" }}</p>
<p>Categories: {{ pages.titles selector="template=category" sep=", " }}</p>Use {{#pages}} when you need a block loop. Use inline pages.* helpers for scalar outputs.
languages / lang
languages and lang expose the language system.
Common properties include:
languages.countlanguages.currentlanguages.defaultlanguages.isMultiLanguagelanguages.alllanguages.{name}
Example:
{{#if languages.isMultiLanguage}}
Current language: {{ languages.current.title }}
{{/if}}Inside {{#languages}}, each language item commonly exposes:
lang.idlang.namelang.titlelang.isDefaultlang.isCurrentlang.urllang.httpUrllang.locale
site
site provides site-level values.
Common properties include:
site.namesite.urlsite.httpUrlsite.httpHostsite.localesite.yearsite.assetssite.templatessite.adminUrlsite.adminProfileUrlsite.adminLogoutUrl
Settings-style access may also be available:
{{ site.setting key="company_name" }}
{{ site.setting key="phone" }}Admin-oriented site helpers are useful for authenticated utility UI:
<a href="{{ site.adminUrl }}">Dashboard</a>
<a href="{{ site.adminProfileUrl }}">Profile</a>
<a href="{{ site.adminLogoutUrl }}">Log out</a>Use site-level settings for stable global values, not for content that should belong to a Variable or a managed page-level object.
now
now provides current time values.
Common properties include:
now.timestampnow.datenow.datetimenow.yearnow.monthnow.day
Example:
<footer>© {{ now.year }} {{ site.name }}</footer>attr
attr exposes values passed into a Variable:
{{! Usage: [[my-widget title="Hello" color="blue"]] }}
<div style="color: {{ attr.color | default("black") }}">
<h3>{{ attr.title | default("Default Title") }}</h3>
</div>attr should stay small and explicit. If a fragment needs a large editable data model, it probably wants a Component instead of a Variable.
loop
loop is available inside loop blocks such as:
{{#each}}{{#pages}}{{#languages}}
Common properties:
loop.indexloop.index1loop.firstloop.lastloop.lengthloop.evenloop.odd
Example:
{{#each page.children as="child"}}
<div class="{{#if loop.odd}}row-alt{{/if}}">
{{ loop.index1 }}. {{ child.title }}
</div>
{{/each}}this
Inside {{#each}}, this is the current loop item:
{{#each page.children}}
<a href="{{ this.url }}">{{ this.title }}</a>
{{/each}}this and a named alias normally point to the same current item.
@index
@index is shorthand for loop.index.
Example:
{{#each page.children as="child"}}
{{#if @index == 0}}
<h2>{{ child.title }}</h2>
{{else}}
<p>{{ child.title }}</p>
{{/if}}
{{/each}}Component Root-Level Fields
In Component templates, the current Component instance fields are often injected as root-level variables:
<h1>{{ title }}</h1>
{{#if showGallery}}
<div class="gallery">
{{#each images as="img"}}
<img src="{{ img.url }}">
{{/each}}
</div>
{{/if}}This is one reason Component templates feel simpler than generic page-level templates.
Reserved names should not be reused casually as custom field names if they would collide with core context objects such as:
pagepagesuserlanguageslangsitenowattrloopthis@index
Component Field Helper Reference
Facet works with several Component-specific helper contracts that are not the same as general {{ expr }} output.
Single Image Field Helpers
Single image fields commonly support:
{field}{field.raw}{field.webp}{field.name}{field.description}{field.width(N)}{field.width(N).webp}{field.height(N)}{field.height(N).webp}{field.size(W,H)}{field.size(W,H).webp}
Example:
<img src="{hero.width(1200).webp}" alt="{hero.description}">
<a href="{photo.raw}" download>Download original</a>Multi-image Field Helpers
Inside {{#each gallery}}, images items commonly support:
{{this}}{{this.raw}}{{this.webp}}{{this.name}}{{this.description}}{{this.width(N)}}{{this.width(N).webp}}{{this.height(N)}}{{this.height(N).webp}}{{this.size(W,H)}}{{this.size(W,H).webp}}
Example:
{{#each gallery}}
<figure>
<img src="{{this.width(600).webp}}" alt="{{this.description}}">
<figcaption>{{this.name}}</figcaption>
</figure>
{{/each}}Map Field Helpers
map fields commonly support:
{field}{field.width(N)}{field.height(N)}{field.size(W,H)}
Examples:
{officeLocation}
{officeLocation.width(600)}
{officeLocation.size(800,500)}Use map only for structured location data, not for plain address copy.
Managed Embed Contracts
Managed workflow embeds typically use:
data-form-embeddata-review-embed
Examples:
<div data-form-embed="enterprise-demo-request"></div>
<div data-review-embed="customer-success-reviews"></div>
<div data-form-embed="{contactForm}"></div>
<div data-review-embed="{serviceReview}"></div>Use fixed ids for template-owned workflows and field-backed values for author-selectable workflows.
Filters Reference
Filters transform values before output. The most important rule is simple:
- use filters for formatting
- do not use filters to hide a weak object model
String Filters
Common string filters include:
escape/erawupperlowercapitalizetrimtruncatenl2brstriptagsreplacesplitslicepadwrapslug
Examples:
{{ page.title | upper }}
{{ page.body | striptags | truncate(200, "...") }}
{{ text | nl2br }}
{{ title | slug }}Default Value Filter
default supplies a fallback when the input is missing or null-like in the supported contract:
{{ page.subtitle | default("Untitled") }}If the exact empty-string behavior matters, prefer an explicit ternary.
Number Filters
Common number filters include:
numbercurrencyabsroundceilfloor
Examples:
{{ 1234567 | number(0, ".", ",") }}
{{ price | currency("$", 2) }}
{{ ratio | round(2) }}Date Filters
Common date filters include:
datedatetimerelative
Examples:
{{ page.created | date("F j, Y") }}
{{ page.modified | datetime("Y-m-d H:i") }}
{{ page.modified | relative }}URL Filters
Common URL-oriented filters include:
url_encodeurl
Examples:
{{ page.title | url_encode }}
{{ website | url }}JSON Filter
Use json for safe JSON output:
{{ data | json }}This is useful when the template needs structured data in HTML or script-oriented output.
Array and Collection Filters
Common collection filters include:
joinfirstlastcountlengthreversesortpluckuniquebatchkeysvaluesmerge
Examples:
{{ tags | pluck("title") | join(", ") }}
{{ page.children | count }}
{{ items | batch(4) }}Image Filter
Common image filter:
size
Example:
{{ page.image | size(600, 400) }}Hash Filter
Common hash filter:
md5
Example:
{{ user.email | md5 }}Variable System
Variables are reusable template fragments that can be embedded anywhere supported by FaceFlow rendering.
Including Variables
Basic include:
[[my-variable]]With attributes:
[[my-widget title="Hello World" color="blue" count="5"]]Variable Structure
A Variable typically contains:
- HTML template
- optional CSS
- optional JS
- optional attributes
- cache mode
Cache Modes
Common modes include:
staticdynamicauto
Use:
staticwhen the output is broadly cache-friendlydynamicwhen the output depends on user- or request-sensitive runtime stateautowhen the engine should choose based on the Variable behavior
Nested Variables
Variables can include other Variables:
<footer>
[[copyright-notice year="2026"]]
[[social-links]]
</footer>Use nesting to improve reuse and clarity, not to create deep hidden dependency chains.
Layout-Level Syntax
Layout-oriented templates often rely on a few structural placeholders:
{content}{header}{footer}{siteComponents}
Example:
<body>
{header}
{siteComponents}
<main>
{content}
</main>
{footer}
</body>These placeholders belong to layout and shell composition, not ordinary section rendering.
Data Attributes
Common runtime-oriented data attributes include:
data-form-embeddata-review-embeddata-fb-mapdata-fb-map-fielddata-component-*data-form-ajaxdata-variabledata-loading
Use these when the runtime contract explicitly documents them. Do not invent parallel attributes casually.
Media References
Some FaceFlow rendering contexts may expose managed media reference patterns such as:
@image:filename@file:filename
These are implementation-side representations of managed assets. In authored templates, prefer the documented helper or object output forms rather than relying on raw storage references.
Rendering Pipeline
A practical Facet rendering order usually looks like this:
- load the owning FaceFlow object
- resolve the current render context
- inject root-level fields and context objects
- evaluate field helper contracts
- evaluate Facet expressions and block helpers
- resolve Variable embeds
- resolve managed runtime markers such as Forms, Reviews, or maps
- return final output
The important design lesson is that Component field shorthand, Facet expressions, Variable embeds, and managed runtime markers are related but not identical stages.
Security Model
Facet is designed as a governed template layer rather than a raw code execution environment.
Key rules:
- no arbitrary server-side code execution
- root objects are controlled
- filters and block types are whitelisted
- query behavior is constrained
- raw output should be used intentionally
Treat this as a sandboxed template language, not as a fallback scripting engine.
Practical Design Rules
- prefer clear object boundaries over clever template logic
- keep template logic shallow
- use Variables for fragments and Components for section contracts
- use Lists when query and pagination are part of the contract
- review any field helper syntax against the field reference before using it
- review cache-sensitive content before introducing deferred rendering
Cookbook Patterns
Navigation Menu
<nav>
<ul>
{{#pages selector="parent=1, sort=sort" as="item"}}
<li><a href="{{ item.url }}">{{ item.title }}</a></li>
{{/pages}}
</ul>
</nav>Blog Post List
{{#pages selector="template=blog-post, sort=-created, limit=6" as="post"}}
<article>
<h2><a href="{{ post.url }}">{{ post.title }}</a></h2>
<p>{{ post.body | striptags | truncate(250) }}</p>
</article>
{{else}}
<p>No blog posts yet.</p>
{{/pages}}Multi-language Switcher
{{#if languages.isMultiLanguage}}
{{#languages as="lang"}}
<a href="{{ lang.url }}">{{ lang.title }}</a>
{{/languages}}
{{/if}}Breadcrumbs
{{#each page.parents as="p"}}
<a href="{{ p.url }}">{{ p.title }}</a> /
{{/each}}
<span>{{ page.title }}</span>Cache-safe User Welcome
{{#deferred skeleton-width="10rem" skeleton-height="2rem"}}
{{#if user.isLoggedin}}
<span>{{ user.displayName }}</span>
{{else}}
<a href="/login/">Sign In</a>
{{/if}}
{{/deferred}}FAQ
When should I use {{#pages}} vs {{#each}}?
- use
{{#each}}when the data already exists in the current context - use
{{#pages}}when the template must query the data
What is the difference between {{ }} and {{{ }}}?
{{ ... }}is escaped output{{{ ... }}}is raw output
Use escaped output by default.
Can I nest loops?
Yes, but only when the object model remains readable. If nested loops are compensating for a weak content contract, stop and revisit the design.
Why does a field return null or empty output?
Common causes:
- wrong context
- wrong field name
- using the wrong syntax family for the current object
- expecting a helper on a field that does not support it
How should I debug template problems?
Start in this order:
- confirm the owning object contract
- confirm the right syntax family
- confirm the available context objects
- reduce the template to the smallest reproducible fragment
- then rebuild from there