No description https://nara-lang.org
  • Rust 57.8%
  • Handlebars 21.9%
  • TypeScript 10.4%
  • CSS 4.7%
  • HTML 3.4%
  • Other 1.8%
Find a file
2026-04-18 12:29:13 -05:00
+content feat: more spec 2026-04-18 12:29:13 -05:00
+devops feat: build config 2026-02-13 21:42:59 -05:00
src feat: have yaml files generate TOC via rust method 2026-03-20 07:47:17 -05:00
.gitignore feat: single TS bundle entrypoint 2026-02-13 20:40:22 -05:00
AGENTS.md
bun.lock feat: styles for stderr in code snippets 2026-02-13 21:10:35 -05:00
Cargo.lock feat: pre-build nara bytecode w compiler binary 2026-02-13 21:39:46 -05:00
Cargo.toml feat: pre-build nara bytecode w compiler binary 2026-02-13 21:39:46 -05:00
dev.ts feat: lint & remove old JS file 2026-02-13 20:49:36 -05:00
flake.lock
flake.nix
package.json feat: styles for stderr in code snippets 2026-02-13 21:10:35 -05:00
README.md feat: api docs internals field 2026-02-20 21:55:22 -05:00
schema.yaml
thp-docs.toml feat: pre-build nara bytecode w compiler binary 2026-02-13 21:39:46 -05:00

THP docs

Custom CMS built for THP.

Usage

This program does these things:

  • Read config file thp-docs.toml

The config file declares the content_folder (e.g. content_folder = "content"). It also requires a narac field which must point to the Nara compiler executable (e.g. narac = "/usr/bin/narac").

Inside the content folder, the program expects:

  • A +static folder for static assets.
  • A +routes folder for the page hierarchy.

Then, based on those 2 things:

  • In dev mode, sets up hot reloading on +routes and serves the routes as full html pages. On each request fully processes the file.
  • In build mode, walks +routes & generates a full, static html page for each route it encounters.

Routes

Inside the routes folder is where the actual pages go. Each file (with exceptions) inside matches to a route. For instance, these files:

- +content/
  - +routes/
    - index.html
    - install.md
    - support/
      - forum.hbs

would create 3 routes: /, /install and /support/forum

If a directory is requested (e.g., /support/), the program will look for an index file with any of the supported extensions inside that directory.

Supported extensions

The program supports html, markdown, handlebars & yaml files.

Nara Code Blocks in Markdown

In markdown files, you can use nara code blocks. If you add a :compile flag to the language tag, the CMS will attempt to compile the code using the narac compiler specified in the config.

```nara:compile
// This code will be compiled to bytecode
let x = 10;
print(x);
```

The compiled bytecode is then passed to the interactive playground component. If compilation fails, the error message will be shown in the console and the build will continue with an error message in the bytecode field.

+layout files

Each folder can have a single +layout file. Such file works as a "shell" for the rest of routes, and its descendants.

- +content/
  - +routes
    - support/
      - +layout.hbs
      - forum.hbs
      - stack_overflow.hbs
      - self_managed/
        - phone.hbs

In the example above, the +layout.hbs file will be used as a shell for all files in the folder (forum, stack_overflow), AND for self_managed/phone.

Layouts are nested. If self_managed/ also had a +layout.hbs, then phone.hbs would be wrapped by self_managed/+layout.hbs, which would then be wrapped by support/+layout.hbs. This works from the innermost file out to the root of the +routes folder.

There can be multiple +layout files, but only one per folder.

The layout file MUST be HBS, and it MUST have a {{{children}}} tag inside it. This tag is where the content of the child pages will be rendered.

File Tree in Layouts

Layout files have access to a file_tree variable containing all routes in the layout's directory and its subdirectories. This is useful for rendering navigation menus.

Each entry in file_tree has:

  • name: Display name (e.g., "Getting Started")
  • path: URL path (e.g., "/learn/getting-started")
  • is_dir: Whether the entry is a directory
  • children: Child entries (for directories)

Example usage in a layout:

<nav>
    <ul>
        {{#each file_tree}}
        <li>
            <a href="{{this.path}}">{{this.name}}</a>
            {{#if this.is_dir}}
            <ul>
                {{#each this.children}}
                <li><a href="{{this.path}}">{{this.name}}</a></li>
                {{/each}}
            </ul>
            {{/if}}
        </li>
        {{/each}}
    </ul>
</nav>

+order.yml files

By default, the file tree is sorted alphabetically with auto-prettified names (e.g., getting-started.md becomes "Getting Started"). To control the order and display names, create a +order.yml file in the directory.

- path: index
  name: Introduction

- path: variables
  name: Variables & Data Types

- path: functions
  name: Functions

- path: advanced
  name: Advanced Topics

Each entry has:

  • path: The file or folder name without extension (e.g., index for index.md)
  • name: The display name to show in navigation

Behavior:

  • If +order.yml exists, only listed entries appear in the nav (unlisted files are hidden)
  • If +order.yml does not exist, all files appear alphabetically
  • Each directory can have its own +order.yml (nested, not inherited)
  • Missing entries (listed in manifest but file doesn't exist) produce a warning

API Documentation

The program supports generating API documentation from YAML files.

YAML Schema

Files with the .yaml extension are treated as API documentation. They must follow a specific schema:

title: std
description: Core language features.
internals: |
  This module is implemented in C++ and exposed via the Nara runtime.
  It uses the `libuv` library for asynchronous I/O.

refs:
  - id: FileDescriptor
    name: FileDescriptor
    description: A handle to an open file.
    link: "https://en.wikipedia.org/wiki/File_descriptor"

functions:
  - name: open
    description: Opens a file.
    parameters:
      - name: path
        type: string
        description: The filesystem path.
    return:
      type: "$ref:FileDescriptor"
      description: The opened file handle.
    example: |
      const fd = std.open("/etc/passwd");
      console.log(fd);

+api_layout files

Unlike regular routes, YAML files require a +api_layout.hbs file to be present in the same folder or any parent folder.

The +api_layout.hbs file is a Handlebars template that receives the parsed YAML data in a api map. You can access fields like {{api.namespace}}, {{api.description}}, {{api.types}}, and {{api.functions}} directly.

Note that +api_layout.hbs files are also inherited from parent folders, similar to +layout.hbs files, but they are only used for rendering YAML files.

When a YAML file is rendered, it is first processed by the +api_layout.hbs template. The resulting HTML is then wrapped by any applicable +layout.hbs files, just like regular routes.

Type References

In the YAML schema, types can be plain strings or references to types defined in the types section by prefixing them with $ref:.

When rendered in the template, these are passed as strings (e.g., "$ref:FileDescriptor").

Static assets

The +static folder is where the static assets go. These files are served as-is, without any processing, at the root of the site. For example, +content/+static/tw-out.css is served at /tw-out.css.