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

How to Create A Basic Web App  (20 minutes)


We assume you already created the starter app from the Get Started page.

App Files 

Here are the key directories and files created by tht new:

├── Document Root      Static files (images, etc.)
│   └── thtApp.php         App entry point
├── data               Logs, database files, etc.
└── app                Your THT app files
    ├── pages              Dynamic web pages
    ├── modules            Shared code
    └── settings           Site configuration

SecurityYour THT files are hosted outside of the Document Root directory to prevent anyone from viewing their entire contents as plain text in a browser.


The easiest way to add a web page is to create a .tht file in the pages directory.

The file name is always lowerCamelCase.

The URL for each page is automatically located at the dash-case version of the file name.

File Path                     URL

pages/hello.tht               /hello
pages/helloWorld.tht          /hello-world
pages/misc/myOtherPage.tht    /misc/my-other-page


You can create dynamic URLs in your settings/app.jcon file.

Just add an entry to routes, mapping the URL to a file in the pages directory.

Optional parameters can be added in curly braces, but must be an entire sub-path. (e.g. /page/user{id} is not allowed, but /page/{userId} is okay.)

routes: {
    /my-url:            thisPage.tht
    /another/url:       thatOtherPage.tht
    /blog/{articleId}:  blog.tht

ImportantOnly the characters a-z_-./ are allowed in a route. THT will automatically respond with a 404 error page if any other character is present in the URL. Trailing slashes (directory paths) are not allowed.

Route Params

As you will see shortly, you can access the value of a route param with Web.routeParam(paramName).

Creating a Basic Page (Example) 

This example will cover:

Step 1: Add the Route

Most pages don’t need a route, but for this example, we want to include a dynamic color name in the URL.

Add the following route to settings/app.jcon. It contains a param named color.

routes: {

    /colors/{color}:  /colors.tht

    // other routes...

Step 2: Create the Page

Create a new file pages/colors.tht.

Copy and paste the following code:

TipRead through it line by line to see what’s happening. It’s okay if you don’t understand everything at first. Take note of what is unfamiliar and look it up later in the Language Tour.

// THT will automatically call main() when the page loads.
function main() {

    // Get the current color from the URL
    let pageColor = Web.routeParam('color');

    // Output the full HTML document
        title: 'Color Picker',
        body: html(pageColor),
        css: css(),

// Main page content in an HTML template
// Code lines begin with '::'
// Code expressions are surrounded with '{{ ... }}'
template html(pageColor) {

    <div class="headerBar" style="background-color: {{ pageColor }}" />

        <h1>The {{ pageColor.toUpperCaseFirst() }} Page</h1>
        :: let colorOptions = ['red', 'green', 'blue'];
        :: for (color in colorOptions) {
            :: let colorName = color.toUpperCaseFirst();
            <li><a href='/colors/{{ color }}'>{{ colorName }}</a></li>
        :: }

// Include the THT Base stylesheet, which normalizes styles
// across browsers and adds a modern look & feel.
template css() {

    {{ Css.include('base') }}

    li {
        font-size: 2rem;
    .headerBar {
        height: 4rem;

Step 3: Load the Page

Load the page at http://localhost:8888/colors/red.

You will see something like this:

The Red Page
  • Red
  • Green
  • Blue

Step 4: Experiment

Try playing around with the code.


Each app is self-contained and includes a standalone copy of the THT runtime.

This means you can copy your files up to a server (document root, app, and data) and it should work right away.

Note: You might need to update permissions, for example, using sudo chown -R www-data app.

See Also