Skip to content
forma.
v3.0
☰
Browse documentation
Start here
Build interfaces
Native rendering
Tooling
Security and operations
Architecture
Application guides
API reference

Docs/API reference

FORMA 3.0

@getforma/build

The build function, application configuration, manifests and size-report types.

View source ↗Markdown ↓Source 2006423
On this page

Generated from the published 3.0.0 TypeScript declarations. Signatures, overloads and JSDoc are taken from the package; private class members are omitted. Declaration links point to version-pinned package files.

Use build with a BuildConfig to produce a matching asset and manifest set. Compiler, browser assets and server inputs must describe the same build. This reference documents the library API; the build guide covers commands and project setup.

Read the usage guide or all entry points.

20 exports · published 3.0.0 declarations

ts
import { build } from '@getforma/build';

Values and functions

build#

Function export · Declaration, line 411

ts
declare function build(userConfig: BuildConfig): Promise<BuildResult>;

Run the Forma build pipeline.

Orchestrates: clean, CSS generation, font copying, esbuild bundling (with optional SSR IR emission), island registry generation, content hashing, compression, manifest generation, service worker generation, and budget warnings.

A production build writes into a staging directory beside outputDir and swaps it in only when every step has succeeded, so a build that fails part way leaves the previous output exactly as it was, and nothing beside it (L-21). The application embeds outputDir in its binary, and used to embed half a build after a failure. Watch mode writes in place, as before. Verified by: packages/build/tests/build.test.ts > "leaves the previous build byte-identical when a build fails after writing files" Verified by: packages/build/tests/build.test.ts > "a failed first build leaves no output directory and nothing beside it"

Related declarations: BuildConfig, BuildResult

Exported types

AssetManifest#

Interface export · Declaration, line 307

ts
interface AssetManifest {
    version: 2;
    writer: string;
    app: string;
    build: string;
    aliases: Record<string, string>;
    assets: Record<string, AssetMetadata>;
    routes: Record<string, RouteManifest>;
}

Related declarations: AssetMetadata, RouteManifest

Member notes

build

The deployment identity (FORMA-186, DR-29): 16 lowercase hexadecimal characters computed from the build's own outputs and the writers' versions before anything is named, compiled into every JavaScript bundle (__FORMA_BUILD__, which core compares with the page's data-forma-build), and the same for identical inputs however often they are built, from any directory when built from the project root (esbuild hashes input paths relative to its working directory). dev in watch mode.

AssetMetadata#

Interface export · Declaration, line 299

ts
interface AssetMetadata {
    immutable: boolean;
    integrity: string;
    retained?: boolean;
}

Member notes

immutable

The build guarantees this exact filename is immutable, independent of its spelling.

integrity

Full SHA-384 of the final uncompressed file, used by SRI and the worker.

retained

A file of the previous release kept for tabs still open on it (FORMA-186, L-25).

BuildConfig#

Interface export · Declaration, line 193

ts
interface BuildConfig {
    entryPoints: BuildEntry[];
    routes: Record<string, RouteMapping>;
    cssEntries?: CssEntry[];
    outputDir: string;
    formaAlias?: string;
    codeSplitting?: boolean;
    serviceWorker?: 'on-demand';
    app?: string;
    previewFrame?: boolean;
    fontDir?: string;
    ssr?: boolean;
    ssrEntryPoints?: Record<string, string>;
    watch?: boolean;
    budgetThreshold?: number;
    serverInlined?: string[];
    strict?: boolean;
    diagnosticsJson?: string;
    previousDist?: string;
    security?: boolean;
}

Related declarations: BuildEntry, CssEntry, RouteMapping

Member notes

entryPoints

JavaScript entry points to build

routes

Route-to-asset mapping for manifest generation

cssEntries

CSS entries to generate (tailwind and/or concatenation)

outputDir

Output directory for all built assets

formaAlias

3.x migration bridge for 'formajs'; warns once per build() with importing files. Prefer '@getforma/core'.

codeSplitting

Bundle one shared ESM graph, preserving import() as separately loaded chunks.

serviceWorker

Production worker policy; defaults to on-demand. Only requested, manifest-listed immutable code/style/WASM assets with verified bytes enter its cache.

app

Application/worker ID: 1–63 lowercase letters, digits or hyphens, starting with a letter or digit. If omitted, a valid nearest Cargo package name is used. Otherwise supply it explicitly; it is always written to manifest2.

previewFrame

Copy @getforma/core's preview-frame runtime into the output, for forma-server's preview frame (PageResponse::frame, FORMA-125; FORMA-175). Off by default, where the output is what it was.

On, the build copies dist/formajs-frame.global.js (core 2.1.0 and later; never core's dist/forma-runtime.js, the CDN alias of the auto-mounting runtime) from the core the bundles import, byte for byte, as forma-runtime.<hash>.js, and names it in the manifest under aliases["forma-runtime.js"], where PreviewFrame::load reads it at start and allows it by its SHA-256 hash. Which core: before anything is written, each entry is bundled in memory with the bundles' own esbuild options (so formaAlias, resolved from the working directory, and tsconfig paths lead where they lead the bundles), and every file it loads is mapped to its package; when the bundles import none, the core installed where the build runs. Watch mode writes it unhashed as forma-runtime.js, named the same way in the dev manifest. It is inlined, never fetched: no compressed copies, and no place in the worker's lists. A core without it fails the build with BUILD-805, a runtime forma-server would refuse to inline (empty, not UTF-8, </script, <!--, a carriage return or a NUL) with BUILD-806, and bundles that import cores whose runtimes differ with BUILD-807, before anything is written.

fontDir

Directory containing .woff2 font files to copy

ssr

Enable SSR IR emission

ssrEntryPoints

SSR entry points for IR emission (page name -> entry path)

watch

Enable watch mode

budgetThreshold

Budget threshold in bytes (Brotli-compressed), default 200_000

serverInlined

Files that should keep unhashed copies (e.g. for server-inlined assets). A zero-JS SSR owner cannot request executable server inlining.

strict

Legacy compatibility option. SSR publication always requires the 3.0 server-renderable subset. False and FORMA_STRICT=0 cannot downgrade errors. Every page is checked; watch retains its previous good product on failure.

diagnosticsJson

Also write every SSR diagnostic as JSON to this path (relative to the working directory), whether or not the build fails: the machine-readable report an agent can act on (N12). It must be outside outputDir, which the build replaces whole and serves.

previousDist

The previous release's dist/, which the application's pipeline keeps as a release artifact (FORMA-186, DR-29, L-25). The build copies that release's own hashed assets into the new dist/, listed in the manifest retained and immutable, so a tab opened before a deploy still loads its chunks from the one dist/ the application embeds. One generation: what the previous release itself retained is not copied again. A directory other than outputDir, which the build replaces whole. Leave it out for a first deploy, or when no release is live. The previous dist is trusted like the source: the check below catches a damaged or altered file, not someone who can also rewrite its manifest. Every copied file is checked against the SHA-384 the previous manifest recorded (BUILD-821); a path that is not a usable previous release fails the build (BUILD-820). Ignored in watch mode.

security

Mark this release as one that fixes a vulnerability (L-16, SR45): nothing is retained from previousDist, so no earlier build's asset is served and a revoked build's tabs meet 404s for their lazy chunks. The application's deploy pipeline must mark every such release, a Forma security upgrade included. FORMA_SECURITY_RELEASE=1 (or true, any case) in the environment marks it too; any value other than 1, true, 0, false or empty fails the build (BUILD-822); and a false here does not unmark it.

BuildDiagnostic#

Interface export · Declaration, line 336

ts
interface BuildDiagnostic {
    code: string;
    severity: 'error' | 'warning' | 'note';
    page: string;
    file: string;
    line: number;
    column: number;
    message: string;
    why: string;
    fix: string;
    chain?: BuildDiagnosticChainLink[];
}

One coded SSR diagnostic (FORMA-119). The catalogue, one entry per code with its fix, is packages/compiler/docs/subset.md.

Related declarations: BuildDiagnosticChainLink

Member notes

code

The stable code, e.g. BUILD-101.

severity

Unsupported SSR constructs are always error; note never fails a build.

page

The page (entry outfile without .js) whose module reported it.

file

The file to edit; empty for a build-level diagnostic.

line

1-based line and column in file, as authored; 0 when unknown.

message

The specific report: the construct, what happens, and its fix.

why

The catalogue's why and fix for the code.

chain

BUILD-403: the composition chain from the page down.

BuildEntry#

Interface export · Declaration, line 159

ts
interface BuildEntry {
    entry: string;
    outfile: string;
    ssr?: boolean;
}

getforma /build — Type definitions

Configuration and result types for the Forma build pipeline.

Member notes

entry

Entry point file path

outfile

Output file path (relative to outputDir)

ssr

Disable SSR for this entry in an otherwise SSR-enabled application.

BuildResult#

Interface export · Declaration, line 356

ts
interface BuildResult {
    manifest: AssetManifest;
    buildHash: string;
    warnings: string[];
    diagnostics: BuildDiagnostic[];
    sizes: RouteSize[];
    sizeReport: SizeReport;
}

Related declarations: AssetManifest, BuildDiagnostic, RouteSize, SizeReport

Member notes

diagnostics

Every coded SSR diagnostic the build reported, page by page.

sizes

The size report's routes (FORMA-021, FORMA-190): per route, its class, what it loads cold in raw, gzip -9 and Brotli bytes, Forma's code (@getforma/core and alien-signals as bundled) beside the application's, the service worker it registers, and its ceilings. A production build fails with BUILD-819 before writing its output when a route is over one: Forma's code over N2's FORMA_CODE_CEILING_GZIP (28,100 B; decision brief L-64), all of its JavaScript over its class's (none for a route without an interactive region, 75 KiB, 365 KiB for a canvas). Empty in watch mode, whose unminified bytes are not what a route ships. The same objects as sizeReport.routes.

sizeReport

The one report (FORMA-190): sizes with the service worker, the preview frame's runtime when previewFrame is on (the frame document row), and the build's times by phase. A production build prints it and writes it, without the times (so the output stays the same bytes for the same sources), as size-report.json beside manifest.json. No routes in watch mode.

BuildTimes#

Interface export · Declaration, line 122

ts
interface BuildTimes {
    totalMs: number;
    phases: {
        bundle: number;
        hash: number;
        compress: number;
        manifest: number;
    };
}

Wall-clock milliseconds, per phase of a production build and in all (N7).

ByteSizes#

Interface export · Declaration, line 79

ts
interface ByteSizes {
    raw: number;
    gzip: number;
    brotli: number;
}

Raw (minified), gzip -9 and Brotli-11 bytes.

CssEntry#

Interface export · Declaration, line 167

ts
interface CssEntry {
    input: string | string[];
    outfile: string;
    tailwind?: boolean;
}

Member notes

input

Glob or array of CSS files to concatenate

outfile

Output file path (relative to outputDir)

tailwind

If true, run

tailwindcss /cli on the first input file

FileSize#

Interface export · Declaration, line 113

ts
interface FileSize extends ByteSizes {
    file: string;
}

A file the build writes that is not a route's: the service worker, the preview frame's runtime.

Related declarations: ByteSizes

FrameSize#

Interface export · Declaration, line 117

ts
interface FrameSize extends FileSize {
    sourceRaw: number;
}

The preview frame's runtime in the output: the served file, and core's before the build minified it.

Related declarations: FileSize

Member notes

sourceRaw

Raw bytes of core's dist/formajs-frame.global.js.

RouteCeilings#

Interface export · Declaration, line 74

ts
interface RouteCeilings {
    forma: number;
    javascript: number;
}

What a class may ship, bytes gzip -9: Forma's code, and all of the route's JavaScript.

RouteClass#

Type alias export · Declaration, line 72

ts
type RouteClass = 'no-interactive-region' | 'islands' | 'whole-page-mount';

How a route is classified (DR-35).

RouteManifest#

Interface export · Declaration, line 288

ts
interface RouteManifest {
    mode: 'ssr' | 'browser';
    js: string[];
    modulepreload?: string[];
    css: string[];
    fonts: string[];
    total_size_br: number;
    budget_warn_threshold: number;
    ir?: string;
}

Member notes

modulepreload

Static ESM dependencies only; dynamic import() chunks are intentionally excluded.

RouteMapping#

Interface export · Declaration, line 175

ts
interface RouteMapping {
    js: string[];
    css: string[];
    fonts?: string[];
    canvas?: boolean;
}

Member notes

js

Configured entry base names. The first selects the native owner before static SSR removes its browser output; additional entries must be Browser.

css

Base names (without extension) of CSS files for this route

fonts

Font file names for this route (optional, defaults to all fonts in outputDir)

canvas

Declare the route a canvas (N2, FORMA-190): a page that hosts many modules and is JavaScript-heavy by design. The size report holds all of its JavaScript to 365 KiB gzip -9 instead of the 75 KiB of other pages; Forma's own code stays under N2's 28,100 B either way. It raises nothing for a route without JavaScript. A heavy page that is not a canvas is trimmed or split, not declared.

RouteSize#

Interface export · Declaration, line 90

ts
interface RouteSize extends ByteSizes {
    route: string;
    class: RouteClass;
    canvas: boolean;
    files: RouteSizeFile[];
    forma: ByteSizes;
    application: ByteSizes;
    worker: ByteSizes;
    javascript: ByteSizes;
    ceilings: RouteCeilings;
    exceeded: Array<'forma' | 'javascript'>;
    over: boolean;
}

One route's size report.

Related declarations: ByteSizes, RouteCeilings, RouteClass, RouteSizeFile

Member notes

class

What the route is: the ceilings follow from it (ceilings).

canvas

The route is declared a canvas (canvas: true): 365 KiB of JavaScript instead of 75 KiB.

files

The files the route loads cold: its js and modulepreload lists. Empty for a route with no JavaScript.

forma

@getforma/core and alien-signals as bundled: N2's figure is forma.gzip.

application

Everything else in the route's files: the application's own code and its other dependencies.

worker

The service worker the route registers: sw.js for a route with JavaScript, zero for one without.

javascript

All the JavaScript the route ships: files and worker. The class's JavaScript ceiling is measured on javascript.gzip.

exceeded

Which ceilings the route is over: Forma's code, all of its JavaScript, or both.

over

exceeded is not empty: the build fails.

RouteSizeFile#

Interface export · Declaration, line 85

ts
interface RouteSizeFile extends ByteSizes {
    file: string;
    forma: ByteSizes;
}

One file a route loads cold, with Forma's share of it.

Related declarations: ByteSizes

SizeReport#

Interface export · Declaration, line 136

ts
interface SizeReport {
    version: 1;
    ceilings: {
        forma: number;
        page: number;
        canvas: number;
    };
    routes: RouteSize[];
    worker?: FileSize;
    frame?: FrameSize;
    times?: BuildTimes;
}

The one report of a production build.

Related declarations: BuildTimes, FileSize, FrameSize, RouteSize

Member notes

ceilings

The policy: Forma's code per route, then all of a page's JavaScript, then a canvas's (gzip -9 bytes).

worker

The generated sw.js.

frame

The preview frame's runtime, inlined into every preview document and never fetched (previewFrame); the frame document row.

times

In the printed report and the build result; never in the file.

Find your next answer.

Search Forma 3.0 documentation, guides and examples.