Falz Docs

How it works

This is an optional overview of the model. To learn it by building a project, start with Getting started; the guide introduces each concept when the project needs it.

Source, scheme, output

Falz separates the files being processed from the instructions that process them:

  • Source is the project tree: documents, data, images, or other files you own.
  • Scheme is .falz/schemes/: layout declarations, templates, fragments, and shared assets.
  • Output is dist/ by default: generated files that should never be hand-edited.

Falz skips .falz/ and the configured output directory when scanning the source. Other paths can be excluded with configuration ignore.

A source file is not automatically an output. A matching layout declaration makes it a build entry, selecting a pipe and destination. Input format, output format, and directory structure can all be different.

Layouts choose and compose

For each source directory, Falz looks in the corresponding scheme directory for a layout, then walks upward until it finds one. The nearest layout takes over for that subtree; it does not merge its declarations with the parent layout.

A src="*.md" content rule is evaluated separately in every governed source directory, so normal content matching does not need recursive glob syntax.

The three declarations have different roles:

  • Content matches source files and fills a named slot in an output template.
  • Fragment renders a supporting scheme file into a reusable template slot.
  • Asset writes a file without template wrapping. Top-level assets come from the scheme; nested content assets come from the source.

Templates and fragments also use upward scheme lookup, allowing a subtree to reuse or override shared files. The guide demonstrates this in Layouts; exact matching and lookup behavior is in the layout reference.

Pipes interpret bytes

A pipe receives raw input bytes and returns output bytes. Omitting pipe passes input through unchanged; md converts Markdown to HTML. Custom pipes can parse other formats, read supporting data, or return an alias used in the destination path.

The guide extends a Markdown pipe in Pipes. Runtime details live in the pipe reference, and available contexts and modules in the JavaScript API.

Index prepares; build produces

Custom pipes export transform() and may also export index():

  • index() prepares persistent per-entry blobs and contributes values to shared KV namespaces.
  • transform() produces the bytes the build writes, optionally reading those prepared values.

A static provides/consumes contract declares shared namespace dependencies. Changing a namespace invalidates its consumers, even when their source files did not change.

One-shot indexed projects run falz index and then falz build. Build reads existing index results but does not refresh them. Watch coordinates both phases. Index phase shows why this is useful with a shared post list.

Incremental state connects it all

Falz tracks the inputs that affect each entry, including source, pipes, layouts, fragments, and consumed namespaces. It compares their hashes with generated state in dist/.manifest.json and schedules changed entries. A content-addressed cache can restore previously built artifacts without rerunning transformations.

Index and build have separate dirty checks: changing a page template affects output, not preparatory metadata. Build phase explores those differences using the guide's completed site.