handlebars

handlebars

Deep knowledge for creating and modifying Handlebars templates (.hbs files). Trigger: When user needs to create/modify .hbs templates, add helpers, work with template syntax, or understand Handlebars patterns.

2星標
2分支
更新於 1/24/2026
SKILL.md
readonlyread-only
name
handlebars
description

>

version
"1.0"

When to Use

Use this skill when:

  • Creating or modifying .hbs template files
  • Adding new Handlebars helpers or partials
  • Debugging template rendering issues
  • Understanding existing template patterns in Aurora CLI
  • Working with dynamic code generation

Critical Patterns

Aurora CLI Template Engine Setup

The template engine is configured in src/@cliter/utils/template-engine.ts:

  • Uses handlebars library with handlebars-helpers addon (189+ built-in helpers)
  • Custom helpers are registered in src/@cliter/handlebars/helpers/
  • Partials are registered in src/@cliter/handlebars/partials/
  • Templates are in src/templates/ (back/, front/, pipeline/)

Important: Aurora CLI includes ALL helpers from the handlebars-helpers package automatically. These 189+ helpers are available in every template without any additional configuration.

Helper Registration Pattern

// src/@cliter/handlebars/helpers/my-helper.ts
import * as handlebars from 'handlebars';

handlebars.registerHelper('myHelper', function(param1: string, param2: any, options)
{
    // options.data.root contains all template data
    // options.fn(this) executes block content
    // options.inverse(this) executes else block
    return result;
});

Partial Registration Pattern

// src/@cliter/handlebars/partials/my-partial.ts
import * as handlebars from 'handlebars';

handlebars.registerPartial('myPartial', `
{{#each items}}
    {{ this.name }}
{{/each}}
`);

Handlebars Syntax Guide

Basic Expressions

{{! Comment - not rendered }}
{{ variable }}                    {{! Simple output }}
{{{ rawHtml }}}                   {{! Unescaped HTML }}
{{ helper param1 param2 }}        {{! Helper call }}
{{ object.property }}             {{! Property access }}
{{ ../parentContext }}            {{! Parent context access }}

Whitespace Control

{{~expression}}     {{! Trim whitespace before }}
{{expression~}}     {{! Trim whitespace after }}
{{~expression~}}    {{! Trim both sides }}

Block Helpers

{{#if condition}}
    content if true
{{else}}
    content if false
{{/if}}

{{#each array}}
    {{@index}} - {{@first}} - {{@last}} - {{this}}
{{/each}}

{{#unless condition}}
    content if false
{{/unless}}

{{#with object}}
    {{property}}  {{! Access object.property }}
{{/with}}

Custom Block Helpers (Aurora CLI)

{{#loops 10}}
    {{@index}} {{@first}} {{@last}}
{{/loops}}

{{#eq value1 value2}}
    content if equal
{{/eq}}

{{#unlessEq value1 value2}}
    content if not equal
{{/unlessEq}}

Aurora CLI Helper Categories

String Transformation Helpers

Helper Description Example
toCamelCase Convert to camelCase {{ toCamelCase "my_name" }}myName
toPascalCase Convert to PascalCase {{ toPascalCase "my_name" }}MyName
toKebabCase Convert to kebab-case {{ toKebabCase "myName" }}my-name
toSnakeCase Convert to snake_case {{ toSnakeCase "myName" }}my_name
sumStrings Concatenate strings {{ sumStrings "Hello" " " "World" }}
singleLine Remove line breaks {{ singleLine multiLineText }}

Variable Management Helpers

{{! Set a variable in root context }}
{{ setVar 'myVar' 'value' }}
{{ setVar 'myVar' (someHelper param) }}

{{! Use the variable }}
{{ myVar }}

Array/Object Helpers

{{! Create an array }}
{{ setVar 'items' (array 'item1' 'item2' 'item3') }}

{{! Create an object }}
{{ setVar 'obj' (object key1='value1' key2='value2') }}

{{! Push to array }}
{{ push myArray (object name='newItem') }}

{{! Check if has items }}
{{#if (hasItems myArray)}}
    has items
{{/if}}

Conditional Helpers

{{! Ternary operator }}
{{ ternary condition 'trueValue' 'falseValue' }}

{{! Check if undefined }}
{{#if (isUndefined variable)}}
    is undefined
{{/if}}

{{! Not in array }}
{{#if (notInArray item array)}}
    not in array
{{/if}}

Property Filter Helpers

Most property helpers filter schema.aggregateProperties:

{{! Get properties without timestamps }}
{{#each (getWithoutTimestampsProperties schema.aggregateProperties)}}
    {{ name }}
{{/each}}

{{! Get enum properties }}
{{#each (getEnumProperties schema.aggregateProperties)}}
    {{ name }}: {{ type }}
{{/each}}

{{! Get relationship properties }}
{{#each (getWithRelationshipOneToOneProperties schema.aggregateProperties)}}
    {{ relationship.aggregateName }}
{{/each}}

Import Manager Helper

{{! Initialize imports array }}
{{
    setVar 'importsArray' (
        array
            (object items=(array 'Injectable') path='@nestjs/common')
            (object items='MyClass' path='./my-class')
    )
~}}

{{! Add more imports dynamically }}
{{
    push importsArray
        (object items='AnotherClass' path='./another')
~}}

{{! Render all imports }}
{{{ importManager (object imports=importsArray) }}}

ID Generation Helpers

{{ uuid 'fieldName' }}           {{! Generate deterministic UUID }}
{{ nanoid 'fieldName' }}         {{! Generate NanoID }}
{{ randomIntegerDigits 5 }}      {{! Random integer with N digits }}
{{ randomDecimalDigits 2 3 }}    {{! Random decimal (int.dec) }}

Handlebars-Helpers Package (Built-in)

Aurora CLI includes all 189+ helpers from the handlebars-helpers package. These are available automatically in all templates.

String Helpers (36 helpers)

{{ append "hello" " world" }}        {{! "hello world" }}
{{ camelcase "foo bar" }}            {{! "fooBar" }}
{{ capitalize "hello" }}             {{! "Hello" }}
{{ capitalizeAll "hello world" }}    {{! "Hello World" }}
{{ dashcase "fooBar" }}              {{! "foo-bar" }}
{{ dotcase "fooBar" }}               {{! "foo.bar" }}
{{ ellipsis "long text..." 10 }}     {{! "long te..." }}
{{ hyphenate "foo bar" }}            {{! "foo-bar" }}
{{ lowercase "HELLO" }}              {{! "hello" }}
{{ pascalcase "foo bar" }}           {{! "FooBar" }}
{{ pathcase "fooBar" }}              {{! "foo/bar" }}
{{ prepend "world" "hello " }}       {{! "hello world" }}
{{ remove "foobar" "bar" }}          {{! "foo" }}
{{ replace "foobar" "bar" "baz" }}   {{! "foobaz" }}
{{ reverse "abc" }}                  {{! "cba" }}
{{ sentence "hello. world" }}        {{! "Hello. World" }}
{{ snakecase "fooBar" }}             {{! "foo_bar" }}
{{ split "a,b,c" "," }}              {{! ["a","b","c"] }}
{{ startsWith "hello" "he" }}        {{! true }}
{{ titleize "hello world" }}         {{! "Hello World" }}
{{ trim "  hello  " }}               {{! "hello" }}
{{ truncate "long text" 5 }}         {{! "long..." }}
{{ truncateWords "a b c d" 2 }}      {{! "a b..." }}
{{ uppercase "hello" }}              {{! "HELLO" }}
{{ center "text" 10 }}               {{! Centers with spaces }}
{{#isString value}}is string{{/isString}}

Array Helpers (28 helpers)

{{ after myArray 2 }}                {{! Items after index 2 }}
{{ arrayify value }}                 {{! Converts to array }}
{{ before myArray 3 }}               {{! First 3 items }}
{{ first myArray }}                  {{! First item }}
{{ first myArray 3 }}                {{! First 3 items }}
{{ last myArray }}                   {{! Last item }}
{{ last myArray 2 }}                 {{! Last 2 items }}
{{ length myArray }}                 {{! Array length }}
{{ join myArray ", " }}              {{! "a, b, c" }}
{{ reverse myArray }}                {{! Reversed array }}
{{ sort myArray }}                   {{! Sorted array }}
{{ sortBy myArray "name" }}          {{! Sort by property }}
{{ unique myArray }}                 {{! Remove duplicates }}
{{ itemAt myArray 2 }}               {{! Item at index 2 }}
{{ pluck users "name" }}             {{! Extract "name" from objects }}
{{#inArray "a" myArray}}found{{/inArray}}
{{#isArray value}}is array{{/isArray}}
{{#equalsLength myArray 5}}has 5{{/equalsLength}}

{{#forEach myArray}}
  {{@index}} {{@first}} {{@last}} {{this}}
{{/forEach}}

{{#eachIndex myArray}}
  {{item}} at {{index}}
{{/eachIndex}}

{{#filter myArray}}{{/filter}}
{{#map myArray}}{{/map}}
{{#some myArray}}{{/some}}
{{#withFirst myArray}}{{this}}{{/withFirst}}
{{#withLast myArray 2}}{{this}}{{/withLast}}
{{#withGroup myArray 3}}{{this}}{{/withGroup}}
{{#withSort myArray "name"}}{{this}}{{/withSort}}

Comparison Helpers (24 helpers)

{{#and value1 value2}}both truthy{{/and}}
{{#or value1 value2}}at least one truthy{{/or}}
{{#not value}}falsey{{/not}}
{{#eq a b}}equal{{/eq}}
{{#is a b}}loosely equal{{/is}}
{{#isnt a b}}not equal{{/isnt}}
{{#gt a b}}greater than{{/gt}}
{{#gte a b}}greater or equal{{/gte}}
{{#lt a b}}less than{{/lt}}
{{#lte a b}}less or equal{{/lte}}
{{#compare a ">" b}}comparison{{/compare}}
{{#contains collection value}}found{{/contains}}
{{#has value pattern}}matches{{/has}}
{{#ifEven num}}even{{/ifEven}}
{{#ifOdd num}}odd{{/ifOdd}}
{{#ifNth 10 2}}every 2nd{{/ifNth}}
{{#isTruthy value}}truthy{{/isTruthy}}
{{#isFalsey value}}falsey{{/isFalsey}}
{{#neither a b}}both falsey{{/neither}}
{{ default value "fallback" }}       {{! Returns fallback if undefined }}
{{#unlessEq a b}}not equal{{/unlessEq}}
{{#unlessGt a b}}not greater{{/unlessGt}}
{{#unlessLt a b}}not less{{/unlessLt}}

Math Helpers (16 helpers)

{{ abs -5 }}                         {{! 5 }}
{{ add 1 2 }}                        {{! 3 }}
{{ subtract 5 2 }}                   {{! 3 }}
{{ multiply 3 4 }}                   {{! 12 }}
{{ divide 10 2 }}                    {{! 5 }}
{{ modulo 10 3 }}                    {{! 1 }}
{{ ceil 4.3 }}                       {{! 5 }}
{{ floor 4.7 }}                      {{! 4 }}
{{ round 4.5 }}                      {{! 5 }}
{{ avg myNumbers }}                  {{! Average of array }}
{{ sum myNumbers }}                  {{! Sum of array }}
{{ random 1 100 }}                   {{! Random between 1-100 }}
{{ plus 1 2 }}                       {{! Alias for add }}
{{ minus 5 2 }}                      {{! Alias for subtract }}
{{ times 3 4 }}                      {{! Alias for multiply }}
{{ remainder 10 3 }}                 {{! Alias for modulo }}

Number Helpers (9 helpers)

{{ bytes 1024 }}                     {{! "1 KB" }}
{{ addCommas 1000000 }}              {{! "1,000,000" }}
{{ phoneNumber "1234567890" }}       {{! "(123) 456-7890" }}
{{ toAbbr 1000000 }}                 {{! "1m" }}
{{ toExponential 12345 2 }}          {{! "1.23e+4" }}
{{ toFixed 3.14159 2 }}              {{! "3.14" }}
{{ toFloat "3.14" }}                 {{! 3.14 }}
{{ toInt "42" }}                     {{! 42 }}
{{ toPrecision 3.14159 3 }}          {{! "3.14" }}

Object Helpers (14 helpers)

{{ get object "nested.path" }}       {{! Get nested value }}
{{ getObject object "key" }}         {{! Get key-value pair }}
{{ JSONstringify object }}           {{! JSON string }}
{{ JSONparse jsonString }}           {{! Parse JSON }}
{{ stringify value }}                {{! String representation }}
{{#hasOwn object "key"}}has key{{/hasOwn}}
{{#isObject value}}is object{{/isObject}}
{{#forIn object}}{{@key}}: {{this}}{{/forIn}}
{{#forOwn object}}{{@key}}: {{this}}{{/forOwn}}
{{#extend obj1 obj2}}{{/extend}}
{{#merge obj1 obj2}}{{/merge}}
{{#pick context "a" "b"}}{{/pick}}
{{ toPath "a" "b" "c" }}             {{! "a.b.c" }}

URL Helpers (9 helpers)

{{ encodeURI "hello world" }}        {{! "hello%20world" }}
{{ decodeURI "hello%20world" }}      {{! "hello world" }}
{{ escape value }}                   {{! URL escaped }}
{{ urlResolve base path }}           {{! Resolved URL }}
{{ urlParse url }}                   {{! Parsed URL object }}
{{ stripQuerystring url }}           {{! URL without query }}
{{ stripProtocol url }}              {{! URL without protocol }}
{{ url_encode value }}               {{! Alias for encodeURI }}
{{ url_decode value }}               {{! Alias for decodeURI }}

Date Helpers (3 helpers)

{{ year }}                           {{! Current year }}
{{ date }}                           {{! Current date }}
{{ moment date "YYYY-MM-DD" }}       {{! Format with moment.js }}

Path Helpers (8 helpers)

{{ basename "/a/b/file.txt" }}       {{! "file.txt" }}
{{ dirname "/a/b/file.txt" }}        {{! "/a/b" }}
{{ extname "file.txt" }}             {{! ".txt" }}
{{ stem "file.txt" }}                {{! "file" }}
{{ resolve "a" "b" "c" }}            {{! Absolute path }}
{{ relative "/a/b" "/a/c" }}         {{! "../c" }}
{{ segments path 0 2 }}              {{! Path segments range }}
{{ absolute path 1 }}                {{! Directory segment }}

Collection Helpers (2 helpers)

{{#isEmpty collection}}empty{{/isEmpty}}
{{#iterate collection}}{{this}}{{/iterate}}

Inflection Helpers (2 helpers)

{{ inflect count "item" "items" }}   {{! Pluralization }}
{{ ordinalize 1 }}                   {{! "1st" }}
{{ ordinalize 22 }}                  {{! "22nd" }}

Regex Helpers (2 helpers)

{{ toRegex "pattern" "gi" }}         {{! Creates RegExp }}
{{#test "hello" "ell"}}matches{{/test}}

HTML Helpers (7 helpers)

{{ sanitize "<b>text</b>" }}         {{! "text" }}
{{{ ul myArray }}}                   {{! <ul><li>...</li></ul> }}
{{{ ol myArray }}}                   {{! <ol><li>...</li></ol> }}
{{{ css "styles.css" }}}             {{! <link rel="stylesheet"...> }}
{{{ js "script.js" }}}               {{! <script src="..."></script> }}
{{ attr attributes }}                {{! Stringifies HTML attributes }}
{{ thumbnailImage image }}           {{! Figure with thumbnail }}

Markdown Helpers (2 helpers)

{{{ markdown "**bold**" }}}          {{! <strong>bold</strong> }}
{{{ md "./file.md" }}}               {{! Rendered markdown file }}

Misc Helpers (5 helpers)

{{ typeOf value }}                   {{! "string", "array", etc. }}
{{ noop }}                           {{! Renders block without processing }}
{{ option "key" }}                   {{! Get value from options }}
{{#withHash key="value"}}{{key}}{{/withHash}}
{{ frame }}                          {{! Frame-related helper }}

Logging Helpers (11 helpers)

{{ log "message" }}                  {{! Console log }}
{{ info "info message" }}            {{! Info level }}
{{ warn "warning" }}                 {{! Warning level }}
{{ error "error" }}                  {{! Error level }}
{{ success "done" }}                 {{! Success message }}
{{ ok "ok" }}                        {{! Ok message }}
{{ danger "danger" }}                {{! Danger message }}
{{ bold "text" }}                    {{! Bold formatting }}
{{ _debug value }}                   {{! Debug output }}
{{ _inspect value }}                 {{! Inspect value }}

Full Reference: See references/handlebars-helpers-reference.md for complete documentation.


Decision Tree

Need string transformation? → toCamelCase, toPascalCase, toKebabCase, toSnakeCase (Aurora)
                           → camelcase, pascalcase, snakecase, dashcase (handlebars-helpers)
Need to store temporary data? → setVar
Need to build arrays/objects? → array, object, push
Need conditional rendering? → if, unless, eq, unlessEq, ternary, and, or, not, compare
Need to iterate? → each, loops, forEach, eachIndex, forIn, forOwn
Need to filter properties? → get*Properties helpers (Aurora custom)
Need to manage imports? → importManager with importsArray
Need unique IDs? → uuid, nanoid
Need math operations? → add, subtract, multiply, divide, ceil, floor, round
Need string manipulation? → trim, split, replace, truncate, append, prepend
Need array operations? → first, last, sort, unique, filter, map, join
Need object access? → get, hasOwn, forIn, forOwn
Need URL handling? → encodeURI, decodeURI, urlParse, stripQuerystring
Need path operations? → basename, dirname, extname, resolve

Code Examples

Example 1: Creating a New Helper

// src/@cliter/handlebars/helpers/is-required-property.ts
import * as handlebars from 'handlebars';
import { Property } from '../../types';

handlebars.registerHelper('isRequiredProperty', function(
    property: Property,
)
{
    return !property.nullable && !property.hasOwnProperty('defaultValue');
});

Example 2: Using Multiple Helpers in Template

{{! Generate TypeScript interface }}
export interface {{ toPascalCase schema.moduleName }}Input
{
{{#each (getWithoutTimestampsProperties schema.aggregateProperties)}}
    {{ toCamelCase name }}{{#if nullable}}?{{/if}}: {{ getDtoTypeProperty this ../config }};
{{/each}}
}

Example 3: Complex Import Management

{{
    setVar 'importsArray' (
        array
            (object items=(array 'Injectable' 'Inject') path='@nestjs/common')
    )
~}}
{{#each (getEnumProperties schema.aggregateProperties)}}
{{
    push ../importsArray
        (object items=(toPascalCase name) path='@api/graphql')
~}}
{{/each}}
{{{ importManager (object imports=importsArray) }}}

Example 4: Conditional Blocks with Context

{{#each (getDtoProperties schema.aggregateProperties)}}
{{#if (isAllowProperty ../schema.moduleName this)}}
    {{#eq type ../propertyType.ENUM}}
        // Handle enum type
        {{ toPascalCase ../schema.moduleName }}{{ toPascalCase name }}
    {{else}}
        // Handle other types
        {{ getDtoTypeProperty this ../config }}
    {{/eq}}
{{/if}}
{{/each}}

Commands

# Build after adding helpers
yarn build

# Find all helpers
ls src/@cliter/handlebars/helpers/

# Find helper usage in templates
grep -r "helperName" src/templates/

# Test template rendering
yarn test

Common Mistakes to Avoid

  1. Missing whitespace control: Use ~ to trim unwanted whitespace

    {{! Bad - adds extra lines }}
    {{#if condition}}
    content
    {{/if}}
    
    {{! Good - clean output }}
    {{~#if condition}}
    content
    {{~/if}}
    
  2. Wrong context access: Use ../ to access parent context in loops

    {{#each items}}
        {{ ../schema.moduleName }}  {{! Access parent, not current item }}
    {{/each}}
    
  3. Forgetting to register helper: Add import in src/@cliter/handlebars/helpers/index.ts

  4. Using {{ instead of {{{: For HTML/code output, use triple braces to avoid escaping


Resources

You Might Also Like

Related Skills

cache-components

cache-components

137Kdev-frontend

Expert guidance for Next.js Cache Components and Partial Prerendering (PPR). **PROACTIVE ACTIVATION**: Use this skill automatically when working in Next.js projects that have `cacheComponents: true` in their next.config.ts/next.config.js. When this config is detected, proactively apply Cache Components patterns and best practices to all React Server Component implementations. **DETECTION**: At the start of a session in a Next.js project, check for `cacheComponents: true` in next.config. If enabled, this skill's patterns should guide all component authoring, data fetching, and caching decisions. **USE CASES**: Implementing 'use cache' directive, configuring cache lifetimes with cacheLife(), tagging cached data with cacheTag(), invalidating caches with updateTag()/revalidateTag(), optimizing static vs dynamic content boundaries, debugging cache issues, and reviewing Cache Component implementations.

vercel avatarvercel
獲取
component-refactoring

component-refactoring

128Kdev-frontend

Refactor high-complexity React components in Dify frontend. Use when `pnpm analyze-component --json` shows complexity > 50 or lineCount > 300, when the user asks for code splitting, hook extraction, or complexity reduction, or when `pnpm analyze-component` warns to refactor before testing; avoid for simple/well-structured components, third-party wrappers, or when the user explicitly wants testing without refactoring.

langgenius avatarlanggenius
獲取
web-artifacts-builder

web-artifacts-builder

47Kdev-frontend

Suite of tools for creating elaborate, multi-component claude.ai HTML artifacts using modern frontend web technologies (React, Tailwind CSS, shadcn/ui). Use for complex artifacts requiring state management, routing, or shadcn/ui components - not for simple single-file HTML/JSX artifacts.

anthropics avataranthropics
獲取
frontend-design

frontend-design

47Kdev-frontend

Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts, posters, or applications (examples include websites, landing pages, dashboards, React components, HTML/CSS layouts, or when styling/beautifying any web UI). Generates creative, polished code and UI design that avoids generic AI aesthetics.

anthropics avataranthropics
獲取
react-modernization

react-modernization

28Kdev-frontend

Upgrade React applications to latest versions, migrate from class components to hooks, and adopt concurrent features. Use when modernizing React codebases, migrating to React Hooks, or upgrading to latest React versions.

wshobson avatarwshobson
獲取
tailwind-design-system

tailwind-design-system

28Kdev-frontend

Build scalable design systems with Tailwind CSS v4, design tokens, component libraries, and responsive patterns. Use when creating component libraries, implementing design systems, or standardizing UI patterns.

wshobson avatarwshobson
獲取