Home Documentation Templates Examples Showcase GitHub ↗
Theme

Design philosophy · Build-time guarantees

Contracts.

Nift treats useful project assumptions as contracts when it can verify them simply and predictably during a build. A contract turns “this should still exist” or “this relationship should still be valid” into something the build can check, track and fail on before deployment.

Prefer checked relationships over unchecked strings.

If Nift has enough information to verify a relationship at build time, expressing that relationship explicitly can turn a later runtime surprise into an immediate, local build error.

What Nift means by a contract

A contract is a guarantee that becomes part of the observable build behavior. Contracts can assert existence, structure, dependency relationships, path validity or other conditions that Nift can actually prove from project state.

declare a relationship
        ↓
Nift verifies what it can know
        ↓
record the dependency/requirement where relevant
        ↓
fail clearly if the declared guarantee is not satisfied
        ↓
a successful build becomes evidence that the checked contract held

A successful Nift build is not proof that an entire website or application is correct. It is evidence that the contracts expressed to Nift were satisfied at that checkpoint.

Contracts already appear throughout Nift

FeatureContractual meaning
@input(...)The input exists, can be safely resolved, is incorporated into this output and therefore becomes a dependency.
@dep(...)This output depends on a project resource even though that resource does not directly render content.
@json(...)The data source exists, parses as JSON, optionally satisfies its schema and becomes a dependency.
@pathto(...)The referenced tracked/project destination resolves and remains a requirement of the generated output.
Project contractsA named project-level JSON source exists, referenced members resolve and outputs using it depend on both the declaration and source.

Design guarantees before designing features

Nift's contract approach is also a feature-design discipline. Start with the guarantee rather than with new syntax:

1. What useful guarantee do we want?
2. Does Nift have enough information to verify it?
3. Can it be checked with simple, predictable semantics?
4. Can users understand the contract and its failures easily?
5. Can existing Nift primitives already express it?
6. Only then add the smallest feature required.

This matters because a theoretically verifiable guarantee is not automatically a good Nift feature. The cost of expressing, implementing, explaining and diagnosing a contract must be proportionate to the value it provides. A contract that is possible to enforce but awkward to teach, difficult to diagnose or expensive to maintain can make the language worse even while making one guarantee stronger.

A good contract must be satisfiable and simple enough to be worth satisfying.

The design test is not only "can Nift prove this?" It is also "can Nift prove it with a small, predictable rule that a human can understand from the source and an error message can explain locally?"

Generalize the philosophy before the syntax.

Nift does not need one giant contract DSL. Different features can express different kinds of guarantees, and a general mechanism should only appear when real project contracts demonstrate that the abstraction is useful.

Contracts and dependency tracking belong together

A contract is most useful when the build graph remembers it. If an output depends on a contract source, changing that source should make the output eligible for rebuild. If the declaration itself changes, dependent outputs should also be reconsidered.

That is why project contracts record both their configured source and .nift/config.json as dependencies when referenced.

Contracts should fail clearly

Good contract errors explain the violated guarantee rather than leaking implementation details. Missing inputs, unknown members, namespace collisions, malformed contract data and unsafe paths are errors because the build can no longer establish the promised relationship.

Contracts should be tested as contracts

Nift's own contract features are protected by focused and implementation-independent regression tests. The tests cover successful behavior, failure behavior, incremental transitions, shadowing/collision rules and adversarial neighbors. A feature is not considered complete merely because its happy path renders the expected bytes. The tests are executable evidence that the stated guarantees are actually met.

This same idea scales to serious Nift projects: define the guarantees that matter, encode what can be checked, and make validation part of the development checkpoint rather than an afterthought.

See it in practiceRoute contracts →