A practical guide for Terminalfour administrators. This manual assumes you are already comfortable creating and editing Content Types, Content Layouts, and Page Layouts, and that your layouts are using the Handlebars processor.
What you'll learn
- What Handlebars Partials are and when to reach for them
- The three kinds of partial: standard, partial blocks, and inline
- How to define a partial and call it from any layout
- How to pass parameters in to keep partials flexible
- Three hands-on exercises you can complete in your own instance
1. What is a Partial?
A Handlebars Partial is a reusable fragment of template markup that you can drop into any Page Layout or Content Layout. If you have worked with shared components before, the idea will feel familiar: you write a piece of markup once, give it a name, and then call it wherever you need it.
Partials are registered across your whole publishing environment, so a partial you define once can be reused in layouts for different channels, page layouts, and content layouts. You call a partial by referencing its name in an expression that starts with an angle bracket:
{{> metaTags}}
2. Why use Partials?
Without partials, keeping templates consistent across a large site becomes a maintenance chore. Imagine the same block of markup — a card component, a meta tag block, a footer disclaimer — copied across a dozen layouts. Fixing a bug or updating that structure then means editing every layout by hand, and it is easy to miss one.
Partials give you a single source of truth for any repeated markup:
- Less duplication: write a fragment once and reuse it everywhere.
- Easier maintenance: update the partial in one place, and every layout that calls it benefits at the next publish.
- Cleaner layouts: large repeated blocks move out of the parent layout, leaving it focused on its own structure.
- Consistency: because every layout draws from the same partial, the output is identical wherever it appears.
Good candidates for partials include social media meta tag blocks, reusable card or teaser components, schema.org structured-data snippets, shared navigation markup, and standard analytics includes.
3. The three types of Partial
Terminalfour supports partials in three forms, each suited to a different need:
- Standard partials — a named, reusable fragment stored as a Handlebars Partial content item and called with
{{> partialName}}. Available across your whole environment. This is the most common type. - Partial blocks — a partial used as a wrapper around content, called with
{{#> partialName}} … {{/partialName}}. The wrapped content is rendered wherever the partial outputs{{> @partial-block}}. - Inline partials — a partial defined directly inside a single layout with
{{#*inline "name"}} … {{/inline}}, for reuse within that layout without registering it globally.
4. Defining a Partial
Like Custom Helpers, partials are managed as content items stored inside a dedicated section in your site structure.
A note on the current setup. Managing partials today means navigating to a specific section in your site structure, identified by a section ID that you retrieve with a SQL query. We know this isn't ideal — it asks for database access and knowledge of Terminalfour internals for what is really just a templating task. This is a temporary requirement. A dedicated UI for creating and managing partials is planned, and when it ships, every partial you have already created through the current workflow will appear there automatically. Nothing will need to be migrated or recreated. Until then, the steps below walk you through the current process.
Step 1 — Find the partials section
Locate the section where partials are stored by running this query against your Terminalfour database:
SELECT * FROM config_option WHERE config_key='handlebars.partialsSectionId'
This returns the section ID for the section where partials are created and managed. Make a note of it. If you can't run SQL against your instance, contact Client Support and they can provide the section ID for you.
Step 2 — Open the section
Navigate to that section in Site Structure. The quickest way is to open any section, then edit the URL in your browser so it references the section ID from Step 1, for example:
https://your-instance.terminalfour.net/terminalfour/page/section#edit/<YOUR_SECTION_ID>
Step 3 — Create a content item
Inside the partials section, create a new content item. Only one Content Type is enabled here, but if you are asked to choose one, select Handlebars Partials. The content item has two elements:
- Name — this becomes the registered name of the partial and is how you reference it in layouts. A name of
articleCardmeans you call it as{{> articleCard}}. Use camelCase to avoid issues. - Code — the Handlebars and/or markup that makes up the partial.
The status of the content item is ignored for partials, but we recommend saving and approving it to avoid confusion later.
5. Using a Partial in a layout
Once a partial is defined, calling it in any layout is straightforward:
{{> articleCard}}
The > character is Handlebars' syntax for invoking a partial. At publish time, Terminalfour looks up the partial by name and inlines its output at that point in the template. You can call the same partial as many times as you like within a single layout:
<div class="featured">
{{> articleCard}}
</div>
<div class="listing">
{{> articleCard}}
{{> articleCard}}
</div>
Note: a partial can process any Handlebars code, but T4 Tags inside a partial will not be processed. Keep partials Handlebars-only.
6. Passing parameters into a Partial
Partials are processed in the context in which they are used. So if a partial includes something like {{sectionName}}, it will output a different value depending on where it is called.
By default a partial inherits the full data context of the layout that calls it, so any variable available in the parent layout is available inside the partial too. That works for simple cases, but you'll often want to pass specific values explicitly to make a partial more flexible and self-contained. You do this with hash arguments on the partial call:
{{> articleCard title="Latest News" showImage=true summary=(publish element="Summary") maxWords=80}}
Inside the partial, those values are available as regular Handlebars variables:
{{! articleCard partial }}
<div class="card">
{{#if showImage}}
<img src="{{imageUrl}}" alt="{{title}}" />
{{/if}}
<h3>{{title}}</h3>
<p>{{truncate summary maxWords}}</p>
</div>
Hands-on Exercise 1: Build and reuse a standard partial
In this exercise you'll create a reusable "promo card" partial and call it from a Content Layout, passing values in as parameters. Work through it in your own instance.
Goal
A single promoCard partial that renders a heading, a summary, and a call-to-action button — reusable across any layout, with the content passed in each time.
Steps
- Find your partials section using the SQL query from Section 4, and open it in Site Structure.
- Create a new content item using the Handlebars Partials Content Type.
- Set the Name to
promoCard(camelCase — this is the name you'll call). - In the Code element, add the following markup:
<div class="promo-card"> <h3>{{title}}</h3> <p>{{summary}}</p> <a class="btn" href="{{url}}">{{linkText}}</a> </div> - Save and approve the content item.
- Open a Content Layout that uses the Handlebars processor (or create one on a test Content Type).
- Call your partial, passing in the values it needs as hash parameters:
<section class="promos"> {{> promoCard title=(publish element="Heading") summary=(publish element="Summary") url=(publish element="Link") linkText="Read more"}} </section> - Preview or publish a piece of content that uses the layout, and confirm the card renders with your values.
What to notice
- The partial has no idea where its data comes from — you decide that at the call site by passing parameters. That's what makes it reusable.
- Call
promoCardfrom a second layout to prove the point: change the markup once in the partial and both layouts update at the next publish.
Hands-on Exercise 2: Wrap content with a partial block
Standard partials drop a fragment in on their own. A partial block instead wraps around content you supply at the call site — ideal for a consistent container whose inner content changes every time, such as a callout or notice box.
Goal
A calloutBox partial block that provides a styled container with an optional heading, into which you place whatever content you want.
Steps
- In your partials section, create another Handlebars Partials content item.
- Set the Name to
calloutBox. - In the Code element, add this markup. The key line is
{{> @partial-block}}, which is where your wrapped content will be inserted:<aside class="callout {{variant}}"> {{#if title}} <h4>{{title}}</h4> {{/if}} {{> @partial-block}} </aside> - Save and approve the content item.
- In a Handlebars Content Layout or Page Layout, call the partial as a block using the
{{#> }}syntax. Everything between the opening and closing tags is passed in as the block content:{{#> calloutBox title="Note" variant="info"}} <p>Applications close on 30 June.</p> {{/calloutBox}} - Publish and confirm the output wraps your paragraph in the styled container with the "Note" heading.
Key points for partial blocks
- Open a block partial with
{{#> partialName}}and close it with{{/partialName}}— the closing tag must match the partial name. {{> @partial-block}}inside the partial is where the wrapped content lands. Omit it and the wrapped content is discarded.- You can still pass hash parameters (like
titleandvariantabove) on the same call — they behave exactly as they do for a standard partial.
Hands-on Exercise 3: A Direct Edit link that's always right
This exercise shows off the single most important behaviour of partials: a partial is processed in the context in which it is used. Because of this, a partial can output values that depend on the current page — such as a Direct Edit link — and get them right every time, no matter which section it happens to be published in.
The directEditSection helper outputs the path to Direct Edit for the section currently being published. Wrap it in a partial once, call it from your Page Layout, and every page across your site gets the correct "Edit this page" link with zero per-section configuration.
Goal
An editThisPage partial that outputs a Direct Edit link for the current section, called once from a shared Page Layout footer.
Steps
- In your partials section, create a new Handlebars Partials content item.
- Set the Name to
editThisPage. - In the Code element, add the following. The
directEditSectionhelper does the work — you don't tell it which section to use, because it reads that from the publishing context:<a class="direct-edit" href="{{directEditSection}}">Edit this page</a> - Save and approve the content item.
- Open a Page Layout that uses the Handlebars processor and, in the footer code, call the partial:
{{> editThisPage}} - Assign that Page Layout to two or three different sections (or use one that is already shared across your site).
- Preview or publish pages in each of those sections and hover over the "Edit this page" link. Notice the link target is different in each section — and correct in each case — even though you wrote the partial and the call only once.
Why this works
- The partial contains no hard-coded section —
directEditSectionresolves against whatever section is being published at the moment the partial runs. - Because partials inherit the context of the layout that calls them, the same
{{> editThisPage}}call produces a different, correct link on every page. - This is the real payoff of a single source of truth: one definition, one call, consistent and context-aware output everywhere.
Tip: the same principle applies to anything context-dependent — breadcrumb fragments, canonical URLs, "last updated" stamps, or section-specific metadata. If a value changes per page, a partial can still output it correctly, because it is evaluated where it is used, not where it is defined.
Bonus: Inline partials
When a reusable fragment is only needed within a single layout, you don't have to register a global partial. Define an inline partial right inside the layout with {{#*inline "name"}}, then call it with the usual {{> name}} syntax:
{{#*inline "displayMessage"}}
<p>Message to display: {{{message}}}</p>
{{/inline}}
{{> displayMessage message="This is an example of a message"}}
{{> displayMessage message=(publish element="HTML")}}
An inline partial is only available within the layout (and scope) where it is defined — it is not registered globally like a Handlebars Partial content item.
Quick reference
| You want to… | Use |
|---|---|
| Call a standard partial | {{> partialName}} |
| Pass values into a partial | {{> partialName key="value"}} |
| Wrap content (partial block) | {{#> partialName}} … {{/partialName}} |
| Output wrapped content inside a block partial | {{> @partial-block}} |
| Define a layout-only partial | {{#*inline "name"}} … {{/inline}} |
Things to remember
- Name partials in camelCase.
- Partials process Handlebars only — T4 Tags inside a partial are not processed.
- A partial is evaluated in the context where it is used, so context-dependent helpers (like
directEditSection) output the right value for the current page. - Pass parameters explicitly to keep partials flexible and self-contained.
- Save and approve your partial content items.
- Changes to a partial take effect at the next publish for every layout that calls it.