Clay uses Handlebars templates to generate code. Templates can access your model data and use a rich set of helpers for formatting, logic, and iteration.
Templates use double curly braces to output values:
// {{name}} Model
class {{pascalCase name}} {
constructor() {
this.id = null;
}
}
Clay automatically adds special context variables to help you navigate your model:
Access the complete root model from anywhere in your template:
<!-- Access model name from anywhere -->
<h1>{{clay_model.name}}</h1>
<!-- Count total types -->
<p>Total types: {{clay_model.model.types.length}}</p>
Reference the parent element in the JSON structure:
<p>Parent name: {{clay_parent.name}}</p>
<p>Parent path: {{clay_parent.json_path}}</p>
The JSON property name of the current element:
<p>Current property: {{clay_key}}</p>
Clay provides extensive string manipulation helpers:
| Helper | Example | Output |
|---|---|---|
camelCase |
{{camelCase "user name"}} |
userName |
pascalCase |
{{pascalCase "user name"}} |
UserName |
kebabCase |
{{kebabCase "userName"}} |
user-name |
snakeCase |
{{snakeCase "userName"}} |
user_name |
upperCase |
{{upperCase "hello"}} |
HELLO |
lowerCase |
{{lowerCase "HELLO"}} |
hello |
capitalize |
{{capitalize "hello world"}} |
Hello world |
startCase |
{{startCase "hello_world"}} |
Hello World |
| Helper | Example | Output |
|---|---|---|
pluralize |
{{pluralize "category"}} |
categories |
singularize |
{{singularize "users"}} |
user |
| Helper | Description | Example |
|---|---|---|
pad |
Pads string to length with spaces | {{pad "abc" 5}} → " abc " |
repeat |
Repeats string N times | {{repeat "*" 3}} → *** |
replace |
Replaces part of string | {{replace "hi" "i" "o"}} → ho |
truncate |
Truncates string to length | {{truncate "hello world" 8}} → hello... |
words |
Splits string into word array | {{#each (words "foo bar")}}{{this}}{{/each}} |
split |
Splits string by delimiter | {{#each (split "a,b,c" ",")}}{{this}}{{/each}} |
Compare values in conditional expressions:
| Helper | Description | Example |
|---|---|---|
eq |
Equals (===) | {{#if (eq status "active")}}Active{{/if}} |
ne |
Not equals (!==) | {{#if (ne count 0)}}Has items{{/if}} |
lt |
Less than (<) | {{#if (lt age 18)}}Minor{{/if}} |
gt |
Greater than (>) | {{#if (gt score 100)}}High{{/if}} |
lte |
Less than or equal (<=) | {{#if (lte count 10)}}Small{{/if}} |
gte |
Greater than or equal (>=) | {{#if (gte age 18)}}Adult{{/if}} |
{{#if isActive}}
Active user
{{else}}
Inactive user
{{/if}}
{{#ifCond age '>=' 18}}
Adult
{{else}}
Minor
{{/ifCond}}
The ifCond helper supports these operators:
==, === - Equality!=, !== - Inequality<, <= - Less than (or equal)>, >= - Greater than (or equal)&& - Logical AND|| - Logical OR{{#if (and isActive isPremium)}}
Premium Active User
{{/if}}
{{#if (or isAdmin isModerator)}}
Staff Member
{{/if}}
{{#switch type}}
{{#case 'admin'}}
Administrator
{{/case}}
{{#case 'user'}}
Regular User
{{/case}}
{{#default}}
Unknown
{{/default}}
{{/switch}}
You can match multiple values in a single case:
{{#switch role}}
{{#case 'admin' 'moderator'}}
Staff Member
{{/case}}
{{#case 'user'}}
Regular User
{{/case}}
{{/switch}}
Use propertyExists to check if a property exists in any object:
{{#if (propertyExists items "email")}}
<th>Email</th>
{{/if}}
{{#each users}}
- {{name}} ({{email}})
{{/each}}
Iterate over unique values or unique values by property:
{{!-- Unique values --}}
{{#eachUnique tags}}
<span>{{this}}</span>
{{/eachUnique}}
{{!-- Unique by property --}}
{{#eachUnique items 'category'}}
Category: {{this.category}}
{{/eachUnique}}
Iterate over items selected by JSONPath (uniqueness determined by path, not value):
{{!-- Select array items (each has unique index in path) --}}
{{#eachUniqueJSONPath clay_model '$.types[*]'}}
<h2>{{this.name}} - {{this.category}}</h2>
{{/eachUniqueJSONPath}}
{{#times 3}}
Step {{inc @index}}
{{/times}}
Group items by a property:
{{#group posts by='category'}}
<h2>{{value}}</h2>
{{#each items}}
<p>{{title}}</p>
{{/each}}
{{/group}}
Check the type of values in your templates:
| Helper | Description | Example |
|---|---|---|
isArray |
Check if value is an array | {{#if (isArray items)}}Is array{{/if}} |
isString |
Check if value is a string | {{#if (isString name)}}Is string{{/if}} |
isNumber |
Check if value is a number | {{#if (isNumber count)}}Is number{{/if}} |
isBoolean |
Check if value is a boolean | {{#if (isBoolean active)}}Is bool{{/if}} |
isEmpty |
Check if value is empty | {{#if (isEmpty list)}}No items{{/if}} |
isNull |
Check if value is null | {{#if (isNull value)}}Is null{{/if}} |
isUndefined |
Check if value is undefined | {{#if (isUndefined opt)}}Not set{{/if}} |
Pretty-print objects as JSON:
<pre>{{{json this}}}</pre>
Convert markdown to HTML:
{{{markdown description}}}
{{!-- Increment (useful for 1-based indexes) --}}
Step {{inc @index}}
{{!-- Parse string to integer --}}
{{parseInt "42"}}
{{!-- Check if string contains value --}}
{{#if (includes email "@")}}Valid email format{{/if}}
{{!-- Check if string starts with value --}}
{{#if (startsWith filename "test_")}}Is test file{{/if}}
{{!-- Check if string ends with value --}}
{{#if (endsWith filename ".js")}}Is JS file{{/if}}
Split strings by delimiter and extract parts:
{{!-- Using split helper --}}
{{#each (split "foo,bar,baz" ",")}}
- {{this}}
{{/each}}
{{!-- Using splitAndUseWord to get specific part --}}
{{splitAndUseWord "user-profile-page" "-" 1}}
{{!-- Output: profile --}}
Reuse template fragments with partials. Define them in your generator:
{
"partials": ["partials/header.hbs"],
"steps": [...]
}
Use in templates:
{{> header}}
<div class="content">
{{name}}
</div>
Clay includes 47+ helpers across 8 categories:
clay_list_helpers tool to get detailed examples of all
helpers when working with AI assistants!
clay_model to access the full model when needed