Writing Handlebars
Write Handlebars template expressions for Celigo integrations -- dynamic values in mappings, HTTP bodies, SQL queries, URIs, and filters. Use when building any resource configuration that needs computed, conditional, or formatted field values.
- Skill ID
- celigo/ai/writing-handlebars
- Publisher
- celigo
- Repository
- ai
- Installs
- 0
- Files
- 13
- Synced
- Sep 23, 2026
Open any RiverX project, open the Skills panel in the chat, and search for this identifier. The files are fetched from the source repository at install time.
celigo/ai/writing-handlebarsInstalls these files- SKILL.md
- references/helpers/array.md
- references/helpers/auth.md
- references/helpers/block-helpers.md
- references/helpers/date.md
- references/helpers/encoding.md
- references/helpers/format.md
- references/helpers/helper-index.md
- references/helpers/math.md
- references/helpers/regex.md
- references/helpers/string.md
- references/helpers/syntax-and-recipes.md
- references/helpers/type-logic.md
What this skill tells the agent
<!-- TIER:1 -->
Writing Handlebars Expressions
Handlebars is Celigo's template language for embedding dynamic values into resource configurations. Any string field that the platform evaluates at runtime can contain Handlebars expressions.
Concerns when writing Handlebars:
- Context -- where the expression runs determines what data is available and how output is treated
- Braces -- double
{{ }}vs triple{{{ }}}controls output escaping - Field access --
record.prefix in all contexts (AFE 2.0),@rootfor job/settings/connection, bracket notation for special characters - Helpers -- 79 custom helpers for math, string manipulation, dates, encoding, regex, and more
- Block helpers --
#each,#if,#compare,#withfor iteration and conditional logic - Date/time -- moment.js format tokens with timezone support
Used across exports, imports, mappings, output filters, and APIs.
Where Handlebars Are Used
Mapping extracts
In import mappings[].extract fields, Handlebars concatenates, transforms, or conditionally selects values. The context is the current record.
HTTP request templates
Export and import http blocks use Handlebars in relativeURI, body, headers, and postBody. Triple braces are essential to avoid HTML encoding of query parameters and JSON.
RDBMS SQL queries
SQL queries in rdbms.query use Handlebars with the mandatory record. prefix. Triple braces prevent encoding of SQL-significant characters like commas and quotes. For full SQL patterns (MERGE, upsert, bulk operations, dialect differences), see writing-sql.
Output filters
Expression-based filters on exports use Handlebars to evaluate whether a record passes through or gets skipped.
File paths and names
Dynamic file names in FTP/S3 exports and imports use Handlebars for timestamps and record-derived values.
Delta tokens
Platform-injected variables like {{{lastExportDateTime}}} provide the last successful export timestamp for incremental syncs. These are not record fields -- the platform injects them at runtime into the export's HTTP/query context only.
Quick Reference
Context Decision Matrix (AFE 2.0)
All contexts use record. prefix to access the current record's fields (AFE 2.0). Do NOT use bare field names, data.field, or data.0.field -- those are deprecated AFE 1.0 patterns. Exception: Mapper 1.0 (Salesforce/NetSuite) uses bare field names without record. prefix.
| Where | Syntax | Data prefix | Example |
|---|---|---|---|
| Mapping extract | {{ }} (double) | record. | {{record.firstName}} |
| HTTP relative URI | {{{ }}} (triple) | record. | {{{record.orderId}}} in URI |
| HTTP body / postBody | {{{ }}} (triple) | record. | {{{record.orderId}}} in JSON body |
| SQL query (RDBMS) | {{{ }}} (triple) | record. | {{{record.email}}} in WHERE clause |
| Output filter | {{ }} (double) | record. | {{record.status}} |
| Delta URI parameter | {{{ }}} (triple) | (platform-injected) | {{{lastExportDateTime}}} |
Additional context objects available via @root:
| Object | Description |
|---|---|
record | Current record being processed |
job | Current job metadata |
settings | Integration/flow settings |
connection | Connection object (for auth headers) |
When one-to-many grouping is configured, the data shape changes to batch_of_records -- iterate with {{#each batch_of_records}} to access individual records.
Key Syntax
- `{{{triple-braces}}}` -- raw output, no escaping. Use for URIs, SQL, JSON bodies, file paths -- anywhere commas, quotes, or ampersands matter. In RDBMS, triple braces output the raw value (
value); double braces wrap in single quotes ('value'). Prefer triple and add literal quotes explicitly where needed. - `{{double-braces}}` -- context-dependent formatting. In RDBMS adds single quotes around the value. In URLs, URL-encodes. Use triple braces for explicit control.
- Always use `record.` prefix (AFE 2.0) --
{{{record.fieldName}}}in all contexts, never bare{{{fieldName}}}or{{{data.fieldName}}}(AFE 1.0). Nested fields:{{{record.properties.email}}}. - Exception: Mapper 1.0 (Salesforce/NetSuite) -- uses bare field names without
record.prefix. This is the only context where bare field references are correct.
Related Skills
- configuring-exports > Quick Reference -- export adaptor types, delta sync setup, output filters
- configuring-imports > Quick Reference -- import adaptor types, operation modes, mapping systems
- writing-mappings > Quick Reference -- Mapper 2.0 fields, lookups, conditional mappings
<!-- TIER:2 -->
Syntax Fundamentals
Braces
| Syntax | Behavior | When to use |
|---|---|---|
{{ }} | Context-dependent formatting -- RDBMS wraps value in single quotes ('value'), URLs get URL-encoded | Use only when auto-formatting is desired |
{{{ }}} | Raw output, no escaping or wrapping | Prefer everywhere -- SQL, JSON bodies, URIs, file paths. Add literal quotes yourself where needed |
{{{{ }}}} | Raw block -- contents treated as literal string | Escaping Handlebars syntax itself |
Field access
| Pattern | Meaning |
|---|---|
record.fieldName | Standard field reference -- all contexts (AFE 2.0) |
record.nested.field | Dot-notation for nested objects |
record.[Field With Spaces] | Bracket notation for special characters in field names |
record.items.[0].name | Array index access |
@root.fieldName | Root context -- escape nested #each scope |
../fieldName | Parent context -- one level up from current #each |
this | Current iteration element |
@index / @key | Current array index / object key in #each |
@first / @last | Boolean -- first/last element in #each iteration |
Subexpressions (nesting helpers)
Use () to nest one helper's output as input to another. The inner helper evaluates first:
{{uppercase (split record.fullName " " 0)}} -- split then uppercase the first word
{{{base64Encode (join ":" record.user record.pass)}}} -- join then encode
{{#compare (add record.qty 1) ">" "100"}}...{{/compare}} -- add then compare
{{#each (after record.tags 3)}}...{{/each}} -- slice then iterateSubexpressions can be nested multiple levels deep. Each () resolves inside-out.
Block helpers
{{#each record.items}}...{{/each}}-- iterate array or object{{#if record.active}}...{{else}}...{{/if}}-- conditional{{#compare val1 "==" val2}}...{{/compare}}-- comparison (==,===,!=,!==,<,>,<=,>=){{#with record.address}}...{{/with}}-- change context scope
Date/time formatting
Uses moment.js tokens. Always use triple braces for date output.
Common tokens: YYYY (4-digit year), MM (2-digit month), DD (2-digit day), HH (24h hour), mm (minute), ss (second), SSS (millisecond), Z (timezone offset), X (Unix seconds), x (Unix milliseconds).
Timezone: pass as third argument -- {{{dateFormat "YYYY-MM-DD" record.date "US/Eastern"}}}.
Date arithmetic
dateAdd works in milliseconds:
- 1 hour = 3,600,000
- 1 day = 86,400,000
- 7 days = 604,800,000
Runtime Context at Each Stage
What {{record.X}} or {{settings.Y}} actually resolves to depends on which bubble the expression runs in. The shapes below were captured by setting body: "{{{jsonSerialize this}}}" on import/lookup bubbles and echoing through a mirror endpoint — they represent exactly what's available at runtime.
Import bubble (HTTPImport, NetSuiteDistributedImport, etc.)
Body templates and Handlebars in mappings[].extract run per-record with this context:
{More from celigo
Use this skill in a project
Open any RiverX project, search the Skills panel for celigo/ai/writing-handlebars, and install it in one click.
