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

# The Pre-Compile Pipeline

> How the content compiler validates, resolves, and prepares content before it reaches your users.

The content compiler is the core of Agentic Content Infrastructure's (ACI) safety model. It ensures that nothing reaches your users, not a single page, without being validated against your component schemas, having all references resolved, and being compiled into a self-contained, renderable payload.

But validation doesn't wait for publish. ACI pushes feedback as early as possible: synchronous warnings on every write, lint APIs agents can call at any time, and workspace-level compilation before publishing. The full compile at publish time is the final gate, not the first time you find out something is wrong.

<Info>
  You can run this validation today. In the local developer loop, `aci build --skip-code --content ./.content --out ./.aci/compiled` compiles and checks your content, usually wrapped by a starter script such as `npm run aci:validate`. Write-time warnings and on-demand lint APIs extend the same compiler further left into the editing loop.
</Info>

This is ACI's central thesis: **everything is validated and prepared before it goes live.**

## Shift-Left Validation

ACI pushes validation **as far left as possible**. The full compiler runs at publish time as the final gate, but validation starts much earlier:

```mermaid theme={null}
flowchart LR
    A["Write-time\nwarnings"] --> B["Lint & Typecheck\nAPIs"] --> C["Workspace\ncompilation"] --> D["Publish-time\nfull compile"]

    style A fill:#22c55e,color:#fff
    style B fill:#6366f1,color:#fff
    style C fill:#8b5cf6,color:#fff
    style D fill:#ef4444,color:#fff
```

<CardGroup cols={2}>
  <Card title="Write-Time Warnings" icon="pen">
    When an agent or editor saves a content document, ACI returns synchronous validation warnings on the write response. Schema violations, type mismatches, missing required fields, all surfaced immediately, not at publish time.
  </Card>

  <Card title="Lint & Typecheck APIs" icon="magnifying-glass">
    Agents can call dedicated lint and typecheck endpoints against their workspace at any time. Check a single file, a directory, or the entire workspace. Get structured diagnostics with file paths, field names, and suggested fixes, designed for agents to consume and act on programmatically.
  </Card>

  <Card title="Workspace Compilation" icon="code-branch">
    Run the full compiler against a workspace before publishing. Catch reference errors, dependency issues, and cross-document problems while the work is still in progress, without affecting production.
  </Card>

  <Card title="Publish Gate" icon="shield-check">
    The final compile at publish time is the hard gate. Nothing reaches users unless the full pipeline passes. But by this point, most issues have already been caught and fixed.
  </Card>
</CardGroup>

This model is designed for **agent iteration speed**. An AI agent drafting 50 product pages doesn't want to discover validation errors at publish time. It wants feedback on every write, so it can fix problems in the same editing session. The lint APIs give agents the same fast feedback loop that a TypeScript developer gets from their IDE.

| Concern              | How ACI Handles It                             |
| -------------------- | ---------------------------------------------- |
| Validation           | Write-time warnings + lint APIs + full compile |
| Broken references    | Write-time warning, blocked at publish         |
| Missing translations | Flagged with specific paths at lint time       |
| Schema mismatch      | Synchronous warning on save                    |
| Unknown routes       | Caught at compile time                         |
| Agent feedback loop  | Structured diagnostics on every write          |

## The Compiler Pipeline

The compiler takes two inputs, a **content snapshot** (a specific version) and a **code manifest** (from your frontend build), and runs a predictable pipeline:

```mermaid theme={null}
flowchart TD
    A["Content Snapshot\n(version in a workspace)"] --> C["Content Compiler"]
    B["Code Manifest\n(from frontend build)"] --> C
    C --> D["1. Schema Validation"]
    D --> E["2. Reference Resolution"]
    E --> F["3. Overlay Application"]
    F --> G["4. Route Building"]
    G --> H["5. Dependency Graph"]
    H --> I["6. Payload Hashing"]
    I --> J["Compiled Output"]

    J --> K["Validated Payloads\n(per route)"]
    J --> L["Route Table\n(URL → content)"]
    J --> M["Dependency Graph\n(content → routes)"]

    style C fill:#6366f1,color:#fff
    style J fill:#22c55e,color:#fff
```

<AccordionGroup>
  <Accordion title="1. Schema Validation" icon="shield-check">
    Every content document is validated against the schema defined by its component type in the code manifest. A `HeroSection` expects `headline` (string), `subtext` (string), `image` (asset reference), and `cta` (link). If any field is missing, has the wrong type, or contains an unexpected value, the compiler reports the exact path, field, and error.

    This catches problems that per-field validation at save time cannot, like a component schema changing in a new code version while existing content still references the old structure.
  </Accordion>

  <Accordion title="2. Reference Resolution" icon="link">
    Content documents reference each other. A page includes a hero fragment, which references an image asset, which might have locale-specific variants. The compiler resolves every `$ref` link into a self-contained payload.

    If a reference points to a document that doesn't exist, the compiler fails with a clear error: "Page `/pages/home.json` references fragment `/content/hero.json` which does not exist in this snapshot."

    The output is a **fully denormalized payload** per route with no runtime reference resolution needed.
  </Accordion>

  <Accordion title="3. Overlay Application" icon="language">
    Content can have locale-specific and audience-specific overlays. The English version of a hero might have different copy than the French version. The compiler applies these overlays to produce variant payloads.

    Overlays follow a fallback graph: if `fr-CA` doesn't have a specific override, it falls back to `fr`, then to the base content. The compiler resolves the full chain and produces one concrete payload per variant.
  </Accordion>

  <Accordion title="4. Route Building" icon="signs-post">
    The compiler builds a complete mapping of URL paths to content payloads. Every route on your site is an explicit, validated entry. There are no "discovered at runtime" routes. If a path isn't in the route table, it doesn't exist.

    This means ACI always knows exactly how many pages your site has, what URLs they live at, and what content they contain.
  </Accordion>

  <Accordion title="5. Dependency Graph" icon="diagram-project">
    The compiler builds a graph of which content documents affect which routes. If a shared footer fragment is used by 500 pages, the graph records that dependency.

    This is what makes incremental publishing possible. When the footer changes, ACI queries the graph to find exactly which 500 pages need re-rendering, and ignores the other 49,500.
  </Accordion>

  <Accordion title="6. Payload Hashing" icon="fingerprint">
    Every compiled payload is stored by its fingerprint. If a page's content hasn't changed since the last publish, the fingerprint is identical and ACI skips re-rendering it. This makes republishing fast even for large sites, since only genuinely changed pages are processed.
  </Accordion>
</AccordionGroup>

## Predictable Output Guarantee

The compiler always produces the same output from the same inputs. Given the same content snapshot and the same code manifest, you always get the same payloads, the same route table, the same dependency graph, and the same hashes.

This guarantee means:

* **Reproducible builds**: You can re-compile any historical snapshot and get the same result
* **Safe caching**: Cached compilation results are always valid for their inputs
* **Debuggable failures**: If a compile fails, you can reproduce it exactly with the same inputs
* **Parallel execution**: Multiple compiles can run simultaneously without interfering with each other

## Schema Evolution

Because ACI controls the full pipeline from content to publish, it handles schema changes as a structured, validated process.

When a component schema changes in your frontend code (say a `HeroSection` gains a new required field `badge`), ACI knows about the change through the updated code manifest. The compiler can:

* Identify every content document that uses the old schema version
* Report which documents need updating before the new code can be published
* Validate that updated documents are compatible with both old and new code versions during the transition

### The Contract Change Workflow

Because ACI owns both sides of the content-to-code boundary, schema changes follow a structured workflow:

1. A developer creates a workspace with the updated component schema
2. ACI links the new code workspace with the existing content and runs the compiler
3. The compiler reports every page that violates the new schema
4. A Gradial agent sees the violations and drafts fixes across all affected pages
5. A human reviews and approves the agent's changes
6. The new code artifact and all content updates are merged to main as a single atomic transaction

This turns schema migration from a manual coordination exercise into an automated, validated process. Adding a required field to a component used by hundreds of pages becomes a routine operation, not a risky one.

<Info>
  ACI validates at compile time, not at the moment of editing, so required fields work naturally. Authors can fill in components incrementally during editing, and the compiler catches any missing required fields before publish.
</Info>

***

*Next: [Publishing & Releases →](/aci/architecture/publishing-and-releases)*
