Home Documentation Templates Examples Showcase GitHub ↗
Theme

Core reference · source audited

Template language essentials.

The v4 language is deliberately small. This page is matched against the current v0.3 parser and documents the public primitives we intend people to build new projects around.

The everyday core is tiny.

@content places page content. @input composes reusable files. @pathto creates project-aware paths. $[...] exposes page/build metadata. @getenv reads build-time environment values. @ent emits the supported HTML entities.

@content — place tracked content

@content accepts zero parameters. Internally the parser processes the tracked content through the same input mechanism, so the content becomes part of the dependency graph.

<main>
  @content
</main>

@input(...) — process and insert one file

@input accepts exactly one path. Nift first checks the path as supplied; if it does not exist there, it also checks relative to the directory of the file currently being processed.

@input('templates/partials/header.html')

@content

@input('templates/partials/footer.html')

The inserted file is parsed as Nift source, recorded as a dependency, and can itself contain additional @input calls. Input loops are detected and reported as build errors.

Relative partial composition

templates/
  partials/
    header.html
    navigation.html
<!-- templates/partials/header.html -->
<header>
  @input('navigation.html')
</header>

Because Nift can also resolve relative to the file currently being processed, nested partial structures do not have to repeat project-root paths everywhere.

@pathto(...) — checked paths from the current output

@pathto accepts exactly one value. If the value matches a tracked name, Nift resolves the target's output. Otherwise it treats the value as a concrete path and requires that path to exist.

Tracked-page links

<nav>
  <a href="@pathto('/')">Home</a>
  <a href="@pathto('about')">About</a>
  <a href="@pathto('docs/getting-started')">Getting started</a>
</nav>

Nift calculates the path relative to the output currently being generated. For tracked targets whose output filename is index.html, it resolves to the containing directory rather than forcing index.html into the URL.

Concrete local assets

<link
  rel="stylesheet"
  href="@pathto('public/assets/css/site.css')">

<script
  type="module"
  src="@pathto('public/assets/js/app.js')"></script>

<img
  src="@pathto('public/assets/images/logo.svg')"
  alt="Site logo">

<a href="@pathto('public/files/guide.pdf')">
  Download guide
</a>

If one of those concrete local paths does not exist, the parser reports that the target is neither a tracked name nor an existing file. That gives shared templates a useful build-time correctness check.

Why prefer it to manual relative paths?

<!-- fragile: tied to one output depth -->
<img src="../../assets/images/logo.svg" alt="Site logo">

<!-- project-aware and checked -->
<img
  src="@pathto('public/assets/images/logo.svg')"
  alt="Site logo">

See the full paths guide with more real HTML examples →

$[...] — tracked-page and build metadata

The current parser recognises exactly these 13 metadata names:

Templating essentials
docs/templating
content/docs/templating.html
public/docs/templating.html
templates/docs.html
UTC
04:53:14
04:53:14
Thursday August 13 2026
Thursday August 13 2026
2026
26
Linux
<title>$[title]</title>
<!-- built $[build-date] -->

Metadata reference and practical examples →

@getenv(...) — read one environment variable

@getenv accepts exactly one environment-variable name and writes its value into the generated output. An unset variable resolves to an empty value.

@getenv('NIFT_ENV')
<meta
  name="deployment-environment"
  content="@getenv('DEPLOY_ENV')">
Generated frontend files are still public files.

Do not use @getenv to leak private tokens, passwords or credentials into client-visible HTML/JavaScript.

@ent(...) — emit a supported HTML entity

@ent accepts exactly one value. The mapping below is the complete mapping implemented by the current v4 parser.

InputEmitsInputEmits
`&grave;~&tilde;
!&excl;@&commat;
#&num;$&dollar;
%&percnt;^&Hat;
&&amp;*&ast;
?&quest;<&lt;
>&gt;(&lpar;
)&rpar;[&lbrack;
]&rbrack;{&lbrace;
}&rbrace;-&minus;
_&lowbar;=&equals;
+&plus;|&vert;
\&bsol;/&sol;
;&semi;:&colon;
'&apos;"&quot;
,&comma;.&period;
£&pound;¥&yen;
&euro;§ or section&sect;
+-&pm;-+&mp;
!=&ne;<=&leq;
>=&geq;->&rarr;
<-&larr;<->&harr;
==>&rArr;<==&lArr;
<==>&hArr;<=!=> &nhArr;
...&hellip;
@ent('@')
@ent('&')
@ent('...')
@ent('section')

@dep(...) — advanced escape hatch

@dep is implemented by the parser and accepts one or more existing dependency paths, but it is intentionally documented separately because most projects should not need it. Normal template/content/@input relationships already establish dependencies automatically.

Read the advanced @dep guide →

Escaping literal template characters

In Nift-processed files, prefix literal @, $ and # with a backslash when they would otherwise be interpreted by Nift:

Nift source          Generated output
-----------          ----------------
@media              @media
$HOME               $HOME
#release-notes      #release-notes

This is particularly useful when Nift processes CSS containing rules such as:

@media (min-width: 60rem) {
  .layout {
    display: grid;
  }
}

The generated CSS contains the normal @media rule.