Home Documentation Templates Examples Showcase GitHub
Theme

Project internals

.nift/config.json.

The project config tells Nift where content lives, where generated files go, which extensions and template are the defaults, how builds should use threads and detect changes, and which project-wide JSON contracts are available.

A typical web project

{
  "config": {
    "content-dir": "content/",
    "content-ext": ".html",
    "output-dir": "public/",
    "output-ext": ".html",
    "default-template": "templates/template.html",
    "build-threads": -1,
    "incremental-mode": "modified",
    "minify-exts": [],
    "contracts": {
      "routes": ".nift/routes.json"
    },
    "schemas": ["model/content.schema"],
    "taxonomies": ["model/site.tax"]
  }
}

For a web project, public/ is a useful conventional output directory because many servers, hosts and frameworks already use that name for browser-facing files. Nift does not require the directory to be called public/; it simply uses the value in output-dir.

Fields

FieldMeaning
content-dirBase directory used to derive content paths for tracked names. It must be non-empty.
content-extDefault content-file extension. It must begin with ..
output-dirBase directory used to derive generated output paths. For web projects, public/ is a convenient convention.
output-extDefault output extension. It must begin with ..
default-templateTemplate used by newly tracked items when a different template is not supplied.
build-threadsControls build and incremental-analysis worker count. A positive value uses that many threads; 0 uses hardware concurrency; a negative value is a hardware-concurrency multiplier, so -1 means 1× available hardware threads and -2 means 2×.
incremental-modeHow Nift determines whether dependencies changed: modified, hash, or hybrid.
minify-extsOptional array of final output extensions to minify automatically, for example [".html", ".css", ".js"]. Supported formats are documented on the Minification page.
contractsOptional object mapping project-wide contract namespace names to project-relative JSON source paths. Referenced contracts become checked dependencies and are available through $[...].
schemasOptional ordered array of project-relative .schema definition sources for typed content.
taxonomiesOptional ordered array of project-relative .tax definition sources.

How tracked names become paths

With this config:

{
  "config": {
    "content-dir": "content/",
    "content-ext": ".html",
    "output-dir": "public/",
    "output-ext": ".html",
    "default-template": "templates/template.html",
    "build-threads": -1,
    "incremental-mode": "modified",
    "minify-exts": []
  }
}

a tracked name such as about resolves naturally to:

content/about.html     →     public/about.html

and a nested name:

docs/getting-started

content/docs/getting-started.html
             ↓
public/docs/getting-started.html

The tracked item stores the name/title/template; the project config supplies the default directory and extension rules that turn the name into concrete content and output paths.

Project contracts

The optional contracts object declares project-wide named JSON sources:

"contracts": {
  "routes": ".nift/routes.json",
  "services": "data/services.json"
}

A declared namespace can then be read anywhere through the normal value syntax, for example $[routes.users.list]. Contract namespaces are reserved project-wide, cannot be shadowed by @json or loop bindings, and are loaded only when referenced. Nift records both the contract source and .nift/config.json as dependencies of outputs that use them.

Read the project contracts reference →

Automatic minification

minify-exts is an optional array. A tracked output is minified after rendering when its final extension is listed:

"minify-exts": [".html", ".css", ".js", ".json", ".svg"]

Individual tracked entries can override the project decision with "minify": true or false. Changing the effective setting invalidates the previous incremental build metadata. See the minification guide →

Incremental modes

modified

Uses modification information to decide whether inputs have changed. This is the generated default and is fast for everyday development.

hash

Uses stored content hashes when determining changes. Files and directory dependencies are hashed by content; directories include their names and nested contents deterministically.

hybrid

Checks modification times or content hashes. It catches ordinary timestamp changes quickly while also detecting content changes whose mtime was preserved.

Should you edit it?

Yes, when you want to change project-wide defaults such as moving generated files to public/, changing the default template, or choosing an incremental mode. It is deliberately ordinary JSON so the project setup is inspectable and easy for humans, scripts and AI assistants to understand.

config.json describes the project-wide rules.

tracked.json describes the individual things Nift manages within those rules.

Build hooks

Project-wide pre/post build scripts run ordinary Nift .f files around a build, configured as pre build/post build (generic — run for every build) and the mode-specific variants pre build -all, post build -all, pre build --auto, post build --auto, pre build --repair and post build --repair (run additionally only for that mode). Matching is additive, so each key runs at most once. A hook receives its build context through the environment: NIFT_HOOK_PHASE (pre/post), NIFT_HOOK_MODE (updated/all/names/auto/repair) and, for per-file hooks, NIFT_HOOK_TARGET (the page name). Hooks run through Nift's own parser (no subprocess); project pre-hooks run before the affected-set calculation so generated inputs can change dependencies.

{"config": {
  "content-dir": "content/",
  "default-template": "templates/main.html",
  "pre build": "scripts/pre.f",
  "post build": "scripts/post.f",
  "post build -all": "scripts/deploy.f"
}}

Hooks are expected to run successfully: a failing project pre-hook aborts the build before rendering, and a failing post-hook fails the build visibly. Per-file hooks are configured on individual entries in .nift/tracked.json and run only for the pages a given invocation actually processes.