Skip to main content
Run anvil build to compile your Anvil project for production. The command does two things in sequence: it runs the compiler to scan your routes and emit a typed manifest, then it bundles a self-contained Node.js server. The output is a single ESM file you can run with node or hand off to anvil start.

Usage

anvil build [options]

Flags

-r, --routes <dir>
string
default:"server/routes"
Directory Anvil scans for route files. Must match the layout expected by the manifest loader.
-g, --gen-dir <dir>
string
default:".gen"
Output directory for generated source files. Anvil writes routes.ts and an intermediate server.ts entry point here before bundling.
-o, --out <file>
string
default:"dist/server.mjs"
Path for the final output bundle. The .mjs extension signals that the file is an ES module.
--manifest-only
boolean
Stop after emitting .gen/routes.ts. Skip generating server.ts and skip the bundling step entirely. Useful for CI validation and type-checking without producing a full build artifact.

What the build produces

1

Scan routes and emit the manifest

Anvil walks your routes directory, validates each module’s param names and schemas, and writes a fully-typed routes.ts to the generated sources directory. The console prints how many routes were discovered:
[anvil] manifest: 6 route(s) → .gen/routes.ts
2

Generate the server entry point

Anvil writes a minimal .gen/server.ts that imports your manifest, calls createApp, and starts the HTTP server. This file is the bundle entry point — you don’t need to write or maintain it yourself:
// Generated by `anvil build`. Do not edit.
import { createApp, serve } from 'anvil-sdk';
import { manifest } from './routes.ts';

process.env.NODE_ENV ??= 'production';
const app = createApp(manifest);
const server = await serve(app, { port: Number(process.env.PORT) || 3000 });
console.log(`[anvil] listening on http://localhost:${server.port}`);
3

Bundle the server

Anvil compiles and bundles server.ts targeting Node.js 20, ESM format, with source maps and all node_modules marked as external. The result lands at dist/server.mjs:
[anvil] bundle → dist/server.mjs

Example: default build

anvil build
[anvil] manifest: 4 route(s) → .gen/routes.ts
[anvil] bundle → dist/server.mjs

Example: custom paths

anvil build --routes src/api --gen-dir .generated --out build/app.mjs

Example: manifest-only (CI validation)

Use --manifest-only to validate route structure and schema serializability in a CI pipeline without spending time on the full bundle:
anvil build --manifest-only
[anvil] manifest: 4 route(s) → .gen/routes.ts
--manifest-only is ideal for a lightweight CI validation step. Run it alongside anvil lint to catch both structural errors and schema issues before deploying MCP tools.
The .gen/ directory contains generated files. Add it to .gitignore and treat its contents as build artifacts — never edit them by hand.