THT is in early Beta. We welcome contributors & feedback.

THT Templates

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


Templates look just like functions, but with the template keyword.

The type of template is indicated in the name of the template.

// An HTML template
template pageHtml() {

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


How It Works 

A template is just like a regular function. But instead of code, it acts like freeform multi-line string.

When called, it is transformed and returned as a LockString. Whitespace and extra indentation is trimmed.

TipBecause templates are just functions, they can be be organized into modules and classes.

WarningCalls to the Db, File, and System modules are not allowed within templates. Keeping your front-end (“view”) code separate from your back-end code makes your project easier to work on.

Template Logic 

There are two ways to use THT code in a template.

Expressions {{ ... }}

THT expressions can be embedded with double-curly braces.

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

template pageHtml(userName) {

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


Pepper Lines ::

Lines starting with the Pepper operator :: will be evaluated as inline THT.

Pepper 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.

template userListHtml(users) {

    :: let numUsers = users.length();

    :: if (!numUsers) {
        <p>No users here!</p>
    :: } else {
        <p>There are {{ numUsers }} users:</p>
        :: for (user in users) {
            <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
template postLinkHtml(post) {

    <a href={{ post.url }}>{{ post.title }}</a>


// a list of post links
template allPostsHtml(posts) {

    :: for (p in posts) {
        <li>{{ postLinkHtml(p) }}</li>
    :: }



Template functions are compiled to PHP as pure string concatenation functions, so they usually execute very quickly.

HTML templates are parsed at compile time and cached.

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, Js, Css, Text

HTML Templates

HTML templates provide a few shortcuts that allow you to write markup that is easier to read.

Slash Tags </>

It’s not necessary to include the tag name in closing tags. A single slash is fine.

    This is a <em>special message</> just for you!

Double-Arrow Tags <...>>

Double-arrow tags automatically close at the end of the line.

<h2>> Look at these bullets
  <li>> This is bullet 1
  <li>> This is bullet 2
  <li>> This is bullet 3
Nesting Double Arrow Tags

You can use more than one double-arrow tag per line. They will be closed in the correct order.

// THT template:
<h2>> Unread Messages: <strong>> 2

// will translate to...
<h2>Unread Messages <strong>2</strong></h2>

Triple-Arrow Tags <...>>>

Content inside of triple-arrow tags is passed through verbatim. Extra indent and surrounding whitespace is trimmed.

This is useful for <pre> and <textarea> tags.


    <h1>> My Page
    <p>> An example paragraph


ImportantContent inside triple-arrow tags must be indented.

Dotted Tags <.class>

In place of the tag name, you can include CSS-style selectors to specify the class or classes.

    <.message>> Make sure you <span.callout>do it</>:
    <.button.button-primary>> Press the Button

// will translate to...

<div class='sidebar'>
   <div class='message'>Make sure you <span class='callout'>do it</span>:</div>
   <div class='button button-primary'>Press the Button</div>

Other Behavior & Rules

CSS Templates

THT expressions in CSS should only be used as property values. Characters like ; and { } will be removed.

template siteCss(brandColor) {

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


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

TipSee the Css module for stylesheet helpers.

JavaScript (Js) Templates

THT expressions are converted to JavaScript data values. It handles Strings, Flags, Numbers. Maps & Lists are converted to JSON.

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

// In THT...
mainJs('Bob Johnson');

template mainJs(userName) {

    var userName = {{ userName }};


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

JCON Templates

JCON is a nested data format that is easier to create and edit by hand, than constructing a literal Map.

JCON templates don’t support THT expressions or logic. Also, they return a Map or List instead of a LockString.

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

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

        myOtherKey: true

Litemark (Lite) Templates

Litemark is a lightweight markup language for writing content, documentation, blog articles, forum posts, etc.

NoteTHT expressions aren’t well supported in Litemark templates yet.

template 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 LockString.

template emailText(name) {

     Hello {{ name }},

     Thanks for joining my website!

     -- Webmaster