> ## Documentation Index
> Fetch the complete documentation index at: https://anvil.thatdevguy.in/llms.txt
> Use this file to discover all available pages before exploring further.

# anvil build: Generate the Manifest and Production Bundle

> Scan routes, validate schemas, emit .gen/routes.ts, and bundle a self-contained dist/server.mjs production artifact ready to deploy.

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

```bash theme={null}
anvil build [options]
```

## Flags

<ParamField query="-r, --routes <dir>" default="server/routes" type="string">
  Directory Anvil scans for route files. Must match the layout expected by the manifest loader.
</ParamField>

<ParamField query="-g, --gen-dir <dir>" default=".gen" type="string">
  Output directory for generated source files. Anvil writes `routes.ts` and an intermediate `server.ts` entry point here before bundling.
</ParamField>

<ParamField query="-o, --out <file>" default="dist/server.mjs" type="string">
  Path for the final output bundle. The `.mjs` extension signals that the file is an ES module.
</ParamField>

<ParamField query="--manifest-only" type="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.
</ParamField>

## What the build produces

<Steps>
  <Step title="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:

    ```text theme={null}
    [anvil] manifest: 6 route(s) → .gen/routes.ts
    ```
  </Step>

  <Step title="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:

    ```typescript theme={null}
    // 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}`);
    ```
  </Step>

  <Step title="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`:

    ```text theme={null}
    [anvil] bundle → dist/server.mjs
    ```
  </Step>
</Steps>

## Example: default build

```bash theme={null}
anvil build
```

```text theme={null}
[anvil] manifest: 4 route(s) → .gen/routes.ts
[anvil] bundle → dist/server.mjs
```

## Example: custom paths

```bash theme={null}
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:

```bash theme={null}
anvil build --manifest-only
```

```text theme={null}
[anvil] manifest: 4 route(s) → .gen/routes.ts
```

<Note>
  `--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.
</Note>

<Warning>
  The `.gen/` directory contains generated files. Add it to `.gitignore` and treat its contents as build artifacts — never edit them by hand.
</Warning>
