How to use and configure Ter.


Quick start

Install deno

Ter is built with Deno, so you'll need to have it installed. Once the deno command is available to run in your terminal, follow along.

Build a site

Navigate to a directory with some markdown files and run Ter to build a site.

This command will recursively search for all *.md files in the current directory and generate a site into the _site directory:

deno run -A --unstable

To start a local server with live refresh, pass the --serve flag:

deno run -A --unstable --serve

Command line usage

Run Ter with the --help flag to see usage reference.

deno run --help
Ter -- tiny wiki-style site builder

  ter [options]

  --input     Source directory (default: .)
  --output    Output directory (default: _site)
  --config    Path to config file (default: .ter/config.json)
  --serve     Serve locally and watch for changes (default: false)
  --port      Serve port (default: 8080)
  --drafts    Render pages marked as drafts (default: false)
  --quiet     Do not list generated files (default: false)

Changing input and output paths

Ter takes 2 optional arguments:

If your markdown files are in some other directory, or if you want a different name for the output directory, adjust accordingy, for example:

deno run -A --unstable --input pages --output _dist

Local server with live refresh

Passing --serve flag will start a local server. Ter will automatically rebuild the site and refresh the browser on any file changes.

deno run -A --unstable --serve


Configuration options can be specified in .ter/config.json from the root directory or in any json file specified with --config flag when running Ter.

If the file does not exist, an example configuration file is created before building.


site.titleTitle of your site.
site.descriptionDescription of your site.
site.urlPublished URL address of your site.
site.rootCrumbLabel used for root crumb label (default: "index").
author.nameYour name.
author.emailYour email.
author.urlYour home page.
navigationOptional. Object of navigation items in form of label: path.
locale.dateOptional. Locale used for formatting dates.


  "site": {
    "title": "Your Blog Name",
    "description": "I am writing about my experiences as a naval navel-gazer",
    "url": "",
    "rootCrumb": "index"
  "author": {
    "name": "Your Name Here",
    "email": "",
    "url": ""
  "navigation": {
    "about": "/about",
    "contact": "/contact"
  "locale": {
    "date": "en-US"

Index pages

Ter recursively recreates the source file system on the rendered site and each directory gets an index file listing its content. For example, if the source looks like this:

└── life

... the life directory will get an life/index.html page with an index of its content.

Index sorting

Items in the index are sorted in the following order:

  1. files with pinned: true in the frontmatter are listed at the top and get an ★ symbol;
  2. directories (child index pages);
  3. rest of markdown files, sorted by date.

Markdown in index files

If the source directory contains an file, its content will be injected into the rendered index.html above the index list. This can be useful for describing what the directory content is about or calling out individual pages.

Markdown frontmatter

Ter extracts YAML frontmatter delimited by --- from markdown files. Here’s an example:

title: My page
description: Here’s my description
date: 2022-01-29
  - myTag
  - otherTag
property: value

## My content

Some properties are utilized when building a site.

titleused for page title
descriptionused for page description
tagsused for tags
datedate in YYYY-MM-DD format
pinnedif true, page is listed at the top of index lists
draftif true, file is ignored during site generation
tocif true, page renders table of contents at the top
hideTitleif true, the page title heading is not displayed
logif true on an index page (, all child pages are rendered inline

All other properties are ignored but can be used in templates.

Ignoring files

Any files and folders that start with an _ or . (hidden) are ignored. For example, if there is a _drafts folder in the content directory, it will be skipped during site generation.

Draft pages

In addition, any markdown file with draft: true in the frontmatter will be ignored.

Rendering draft pages

To render files with draft: true, pass --drafts flag to the main command. For example:

deno run -A --unstable --serve --drafts

Ter automatically finds non-working internal links and lets you know about them after building a site. Here's an example output:

Dead links:
/overview -> /non-existent-page-name
/overview -> /some-dead-link


Ter generates a static site which can be deployed anywhere.


To deploy on Vercel, use the following build and output configuration.

NoteIf using non-default input and output folders, update the build command and output directory accordingly.
# Build command
deno run -A --unstable

# Output directory

# Install command
curl -fsSL | DENO_INSTALL=/usr/local sh

Deno Deploy

For Deno Deploy, we can use a GitHub Action to automatically build the site and then deploy it with Deno's deployctl.

Firstly, create a new project on Deno Deploy. Select "Deploy from GitHub", link the repository, and use the production branch. For deployment mode, select “GitHub Actions”.

Next, create a .github/workflows/deno-deploy.yml file in the repository and make changes according to your setup.

GitHub Action (deno-deploy.yml)
name: Deploy to Deno Deploy

    # Change if using a different production branch
    branches: [ main ]
    branches: [ main ]

    name: Deploy
    runs-on: ubuntu-latest
      id-token: write
      contents: read

      - name: Clone repository
        uses: actions/checkout@v3

      - name: Setup Deno
        uses: denoland/setup-deno@v1.1.0

      - name: Build site
        # Change if using non-default input/output directories
        run: deno run -A --unstable main.ts

      - name: Deploy to Deno Deploy
        uses: denoland/deployctl@v1
          # Replace with the project name on Deno Deploy
          project: my-ter-site
          # Change if using non-default output directory
          root: _site