Twig Template Syntax

As of September 2026, all new character sheets now use the Twig template engine instead of the old Blade engine. Twig templates are sandboxed and receive the current entry through the entry object.

Main properties and how to access them

{{ entry.name }}
{{ properties.strength }}
{{ entry.status|raw }}
{% if entry.gender is defined %}
    {{ entry.gender }}
{% endif %}

Values are escaped by default. Use the raw filter only for documented fields that contain trusted HTML.

Conditions and loops

Use native Twig tags for control flow:

{% if properties.strength is defined %}
    Strength: {{ properties.strength }}
{% elseif entry.name %}
    {{ entry.name }}
{% else %}
    Unknown character
{% endif %}

{% for ability in abilities %}
    <h3>{{ ability.name }}</h3>
    {{ ability.entry|raw }}
{% endfor %}

Entry object

The following fields are available where present:

  • entry.name, entry.type, and entry.status
  • entry.category.id, entry.category.code, entry.category.singular, and entry.category.plural
  • entry.tags, and entry.tag_slugs
  • entry.appearances, and entry.traits
  • entry.title, entry.gender, entry.pronouns, and entry.age.

Other objects

The following objects and properties are also available:

  • properties, an object containing character-sheet properties
  • abilities, an object containing the entry's abilities
  • campaign.name, campaign.premium
  • locale with the current ui locale (ex en, en-US, pt-BR)

Properties with special characters

Use bracket notation for property names that are not valid identifiers:

{{ properties['armor-class'] }}

Displaying ranged properties

You can reference ranged properties by simply writing the property name without the range section. For example, if you have a property called level[range:0,10], write {{ properties.level }} in the HTML field.

Legacy Blade syntax

Character sheets versions released before September 2026 continue to use their original Blade engine. See the legacy Blade documentation for those template docs.

Live editing

To allow a property to use Kanka's live editing, call the live() function instead of displaying the property directly with {{ properties.propertyName }}.

{{ live('propertyName') }}

The function takes the property's name as its only argument. It injects a span element with the live-editing properties and the property's rendered value, allowing the value to be edited without manually updating the character sheet.

For example, to make a strength property editable, use {{ live('strength') }}.

Translating character sheets

You can use {{ trans("This is my text") }}. The value in the view is considered the default translation, and will render as This is my text in the character sheet rendering, or as a translation for the user's language if one is defined.

Passing variables to your translation strings is possible using the following syntax: {{ trans("He is :title :name", {title: 'Mr.', name: 'Bob'}) }}, this will render as He is Mr. Bob in the character sheet rendering, or as a translation for the user's language if one is defined, note that for other language translations of an already existing translation string its not necessary to re-declare the variables, they should only be called using : followed by the variable name inside the translation.

Limitations and invalid characters

The default translation strings need to be escaped, meaning you need to write {{ trans("Hello \"world\"") }} or {{ trans('Hello \'world\'') }}.

Javascript variables and APIs

When rendering the character sheet on Kanka, the following javascript constants are defined on the page that expose data related to the entry.

The first one is entityData, an object containing data related to the entry. Note that the properties sluggifies property names. A proper API exposing properties as full objects is described later.

{
    "name": "_Arkansas",
    "is_private": true,
    "type": {
        "id": 1,
        "code": "character",
        "custom": ""
    },
    "properties": {
        "race": "",
        "class": "",
        "subclass": "",
        "alignment": "",
        "level": "1",
        "experience": "0",
        "header-text": "",
        "armor-class": "10 + {DEX_MOD}",
        "layout": "68512a73-49cd-46ec-b8cb-b109f2de3b9f"
    },
    "tags": [
        {
            "id": 68664,
            "name": "Thalian Gods",
            "slug": "thaliangods",
            "url": "https://app.kanka.io/w/thaelia/entities/886710"
        },
        {
            "id": 204875,
            "name": "Arc I - A friendly fundraiser",
            "slug": "arciafriendlyfundraiser",
            "url": "https://app.kanka.io/w/thaelia/entities/2900236"
        }
    ]
}
    

If the current entry is a Character, the following properties are also available in the entityData object.

"type_field": "Test",
"gender": "A concept",
"pronouns": "They/Them",
"is_dead": true,
"title": "The Tester",
"age": "44",
"traits": [
    {
        "name": "Goals",
        "entry": "Find purpose in life",
        "section_id": 2,
        "section": "personality"
    },
    {
        "name": "Hair",
        "entry": "Mostly",
        "section_id": 1,
        "section": "appearance"
    }
],
"races": [
    {
        "id": 37898,
        "name": "Goblin",
        "url": "https://app.kanka.io/w/thaelia/entities/379591"
    },
    {
        "id": 162,
        "name": "Human",
        "url": "https://app.kanka.io/w/thaelia/entities/45494"
    }
],
"families": [
    {
        "id": 34572,
        "name": "Almunia",
        "url": "https://app.kanka.io/w/thaelia/entities/994223"
    }
],
"location": {
    "id": 255254,
    "name": "Troncone Mines",
    "url": "https://app.kanka.io/w/thaelia/entities/1027340"
}
                

Properties API

If the need to interact with the full properties of the entry, which also includes creating, updating and deleting properties, the attributeApis object is exposed.

{
    "all": {
        "method": "GET",
        "url": "https://app.kanka.io/w/thaelia/entities/1/attributes/live-api"
    },
    "create": {
        "method": "POST",
        "url": "https://app.kanka.io/w/thaelia/entities/1/attributes/live-api"
    }
}
                

Abilities API

Lastly, if the need to interact with the abilities of the entry, the abilityApis object details an API that exposes all the abilities as proper objects.

{
    "all": {
        "method": "GET",
        "url": "https://app.kanka.io/w/thaelia/entities/1/entity_abilities/api"
    },
}
                

Handling Errors

When an error happens while rendering a character sheet, a message will warn the user, along with a hint on what went wrong.