Version: v0.6.1 - Beta.  We welcome contributors & feedback.  THanks!



THT introduces template functions, which let you embed HTML and other content within your scripts.

In PHP, it is common to use a third-party template language (e.g. Twig) to keep your front-end code separated from the rest.

Instead, THT supports templates directly, which has some advantages over using a 3rd party language:

How It Works 

Templates look and act just like functions, but use the template keyword (or the T shortcut).

The type of template (e.g. 'html') is indicated in the name of the template.

The body of a template is a freeform multiline string.

When the template function is called, the body is transformed according to its type and then returned as a TypeString, which can then be passed to your output.

Whitespace and extra indentation is trimmed so you can indent however you wish.

    title: 'My Website',
    body: pageHtml()

// An HTML template
template pageHtml() {

    <h1>My Website</h1>
    <p>Welcome to my site!</p>


TipBecause templates are just functions, they can be be organized any way you like: by page, modules, classes, etc.

Template Logic 

There are two ways to include THT logic in a template.

Expressions {{ ... }}

THT expressions can be embedded with double-curly braces.

The result is automatically escaped according to the type of template.

// (You can use `T` as a shortcut for `template`)
T pageHtml($userName) {

    <h1>My Website</h1>
    <p>Hello, {{ $userName.upperCase() }}!</p>


Code Lines --

Lines starting with the Code Line operator -- will be evaluated as inline THT.

Code lines must end in a semicolon or curly brace. If you need a larger block of logic, you should probably put it in a separate function.

T userListHtml($users) {

    -- $numUsers = $users.length();

    -- if !$numUsers {
        <p>No users here!</p>
    -- } else {
        <p>There are {{ $numUsers }} users:</p>
        -- foreach $users as $user {
            <li>{{ $user }}</li>
        -- }
    -- }

Nested Templates 

The output of other templates are included as-is (without escaping) if the template types are the same.

In this way, you can use smaller templates as “partials”.

// a single post link
T postLinkHtml($post) {
    <a href={{ $post.url }}>{{ $post.title }}</a>

// a list of post links
T allPostsHtml($posts) {

    -- foreach $posts as $p {
        <li>{{ postLinkHtml($p) }}</li>
    -- }


Template Types 

The name of your template must end in a suffix that tells THT how it should process the content.

Supported types are:

HTML Templates 

See HTML-C shortcuts for quicker ways to write HTML in your templates.

Extra whitespace inside of multiline tags is automatically trimmed so you can indent your tags without affecting the output with stray spaces.

See also: Format Checker rules for HTML templates.

// An HTML template
template pageHtml() {

    <h1>My Website</h1>
    <p>Welcome to my site!</p>


CSS Templates 

THT expressions within CSS should only be used as property values.

Characters like ; and { } will be removed.

T siteCss($brandColor) {

    header {
        background-color: {{ $brandColor }};


When a CSS TypeString is included in an HTML template, it will wrap the content in a <style> block.

See the Css module for stylesheet helpers.

JavaScript (Js) Templates 

THT expressions within a Js template are converted to JavaScript data values.

It handles Strings, Booleans, Numbers. Maps & Lists are converted to JSON.

When a Js TypeString is included in an HTML template, it will wrap the content in a <script> block and a self-executing function.

// In THT...
mainJs('Tim Plate');

T mainJs($userName) {
    var userName = {{ $userName }};

// When included in an HTML template, it looks like this:
    var userName = "Tim Plate";

JCON Templates 

Jcon templates can be used to define hardcoded data using JCON syntax. It returns a Map or List instead of a TypeString.

THT expressions or logic are not supported in this type of template.

$data = dataJcon();
print($data.myKey[1]);  //= 'list item 1'

T dataJcon() {
        myKey: [
            list item 0
            list item 1

        myOtherKey: true

Litemark (Lite) Templates 

Lite templates support embedded Litemark content for writing page content, documentation, etc.

NoteTHT expressions aren’t well supported in Litemark templates yet. For now, it is recommended that you use Lite templates for content that is not dynamic.

T mainLite() {

    # Heading

    Lorem ipsum thtum.

    - List Item 1
    - List Item 2

Text Templates 

Text templates do not transform or escape the content.

They return a plain string instead of a TypeString.

T emailText($name) {

     Hello {{ $name }},

     Thanks for joining our app!

     - The Team