Skip to main content
This guide takes you from a fresh ACI starter to a working local site. You’ll install dependencies, verify the frontend contract, edit content as plain JSON, validate it, and render it through your own framework, the whole loop, end to end. It runs entirely on your machine.
ACI is currently available to design partners. This quickstart works locally and does not require production cloud access. Request access → for production onboarding.

Prerequisites

  • Node.js 20.19+ and npm
  • An ACI starter repo provided by Gradial
  • A terminal and text editor

Step 1: Install Dependencies

Clone the starter repo you were given, then install dependencies from the starter root:
npm install
The current Astro starter has this shape:
.aci.yaml                         # ACI site contract
.content/                         # Editable source content
.content/config/site.json          # Site configuration
.content/pages/**/_index.json      # Page documents
src/cms/contracts/components/      # Component names, Zod schemas, render modes
src/cms/contracts/layouts/         # Layout slot contracts
src/cms/renderer.ts                # Renderer capsule entrypoint
src/components/                    # Runtime framework components

Step 2: Verify the ACI Contract

Run the doctor command:
npm run aci:doctor
doctor checks .aci.yaml, the @gradial/aci package, registry paths, renderer entry, Node/npm availability, and framework-specific requirements.

Step 3: Compile Contracts and Content

Compile the component and layout contracts:
npm run aci:compile
Then compile and validate source content:
npm run aci:validate
In the current starter, aci:validate compiles .content/ into .aci/compiled. The framework build reads the compiled content from that generated directory.

Step 4: Build and Run

Build the framework site:
npm run build
Start local development:
npm run dev
Open the local URL printed by your framework dev server.

Step 5: Edit Content

Open the homepage content:
code .content/pages/home/_index.json
Find a block in regions.main and change a field:
{
  "id": "hero",
  "component": "home_hero",
  "props": {
    "headline": "Your New Headline Here"
  }
}
Save the file, then run:
npm run aci:validate
npm run build
Refresh your local site and your change is live. That validate → build loop is the same safety path content takes all the way to production: every edit is checked against your component schemas before it renders.
Keep npm run dev running in one terminal and edit content in another. Re-run npm run aci:validate after a content change to recompile .aci/compiled, then refresh.

Content Shape

ACI page content is JSON:
{
  "$type": "page",
  "id": "home",
  "status": "published",
  "layout": "marketing",
  "renderMode": "static",
  "metadata": {
    "title": "Page Title",
    "description": "SEO description"
  },
  "regions": {
    "main": [
      {
        "id": "hero",
        "component": "home_hero",
        "props": {
          "headline": "Welcome"
        }
      }
    ]
  }
}
  • $type: "page" for page documents
  • layout: Which layout contract to use
  • renderMode: How the page should be rendered, such as "static"
  • metadata: SEO and page-level data
  • regions: Named layout regions containing blocks
  • component: The registered component contract name
  • props: Data validated against that component’s Zod schema

Component Contracts

Component contracts live under src/cms/contracts/components/ and should not import runtime components, CSS, browser APIs, or framework-only modules.
import { defineComponentContract } from '@gradial/aci';
import { z } from 'zod';

export const homeHeroContract = defineComponentContract({
  name: 'home_hero',
  schema: z.object({
    headline: z.string().min(1),
    description: z.string().optional(),
    ctaLabel: z.string().min(1),
    ctaHref: z.string().min(1)
  }),
  renderModes: { canStatic: true, canSSR: true, canClientIsland: false }
});
Runtime components are wired separately by the starter’s render code. This separation keeps ACI’s compiler deterministic and avoids pulling framework runtime code into schema extraction.

Common Tasks

Add a New Page

Create a page folder and _index.json:
mkdir -p .content/pages/about
{
  "$type": "page",
  "id": "about",
  "status": "published",
  "layout": "marketing",
  "renderMode": "static",
  "metadata": {
    "title": "About Us",
    "description": "Learn about our company"
  },
  "regions": {
    "main": [
      {
        "id": "hero",
        "component": "home_hero",
        "props": {
          "headline": "About Us",
          "description": "We build great products.",
          "ctaLabel": "Contact us",
          "ctaHref": "/contact"
        }
      }
    ]
  }
}
Then run:
npm run aci:validate
npm run build

Validate Before Committing

npm run aci:doctor
npm run aci:compile
npm run aci:validate
npm run typecheck
npm run build

Use the CLI Directly

Starter scripts usually wrap the CLI for you. The direct equivalents are:
aci build --compile-only
aci build --skip-code --content ./.content --out ./.aci/compiled
aci build --content ./.content
aci doctor
aci dev

Troubleshooting

ACI command not found

Most starters install @gradial/aci locally. Use the starter’s npm run aci:* scripts, or run the local binary with:
npx aci --help

Content changes are not showing

  1. Save the JSON file.
  2. Re-run npm run aci:validate.
  3. Re-run npm run build if your framework reads from .aci/compiled.
  4. Check for JSON syntax or schema validation errors.

Component not found

The component value in content JSON must match a contract exported from src/cms/contracts/components/index.ts.

What’s Next

The Frontend Contract

Go deeper on .aci.yaml, component and layout contracts, and the renderer entrypoint that connects your site to ACI.

Framework Guides

Set up Astro, Next.js, or SvelteKit against the same contract.

Add Components

Define your own components with Zod schemas, render modes, and image slots.

Explore the CLI

Master the commands for building, validating, syncing content, and managing branches.

Next: Frontend Contract →