Skip to main content

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.

Frontend Contract

Agentic Content Infrastructure (ACI) doesn’t own your frontend. Your website code lives in your Git repository, written in whatever framework you choose. ACI integrates with your project through a lightweight frontend contract, three things your project exposes so ACI can build, validate, and render through it.

The Three Parts

Config File

.aci.yaml tells ACI what framework you use, where your components are, and what capabilities your project supports.

Component Registry

Maps CMS content types to your actual components, with schemas that define what content each component accepts.

Render Function

ACI calls your render function with content. Your code returns HTML. That’s the entire rendering interface.

The Config File

The .aci.yaml file lives in the root of your project. It tells ACI the basics:
# .aci.yaml
framework: astro          # astro | nextjs | sveltekit
components: src/components # where your components live
registry: src/registry.ts  # path to your component registry
ACI uses this to detect your project, locate your components, and choose the right build adapter.

The Component Registry

The component registry maps CMS content types to your frontend components and defines the schema for each one:
// src/registry.ts
import { defineRegistry } from '@gradial/runtime'

export default defineRegistry({
  Hero: {
    component: () => import('./components/Hero.astro'),
    metadata: {
      description: 'Full-width hero banner with headline, optional subtext, background image, and call-to-action button.',
    },
    schema: {
      headline: { type: 'string', required: true },
      subtext: { type: 'string' },
      image: { type: 'asset', required: true },
      cta: {
        type: 'object',
        properties: {
          label: { type: 'string', required: true },
          url: { type: 'string', required: true },
        },
      },
    },
  },

  ProductCard: {
    component: () => import('./components/ProductCard.astro'),
    metadata: {
      description: 'Compact product display card with name, price, description, and thumbnail image.',
    },
    schema: {
      name: { type: 'string', required: true },
      price: { type: 'number', required: true },
      description: { type: 'string' },
      thumbnail: { type: 'asset', required: true },
    },
  },
})
The registry serves three purposes:
  1. For the content compiler: schemas are extracted into the code manifest and used to validate content at compile time. If an editor puts a number in the headline field, the compiler catches it.
  2. For rendering: the registry maps content type names to actual component imports, so ACI knows which component to use for each content document.
  3. For agents: the metadata.description field gives AI agents context about each component, so they can make informed decisions about which components to use and how to populate them.
Schemas are defined in code, next to the components that use them. This means the developers who build the components also define what content those components accept. No drift between CMS configuration and code expectations.

The Render Function

ACI calls your project’s render function to produce HTML. The interface is simple:
// src/renderPage.ts
import { defineRenderer } from '@gradial/runtime'
import registry from './registry'

export default defineRenderer({
  registry,
  async renderPage(request) {
    // request.page contains the compiled content payload
    // request.route contains the URL path and metadata
    // Return rendered HTML
    return {
      html: await renderToString(request.page, request.route),
      headers: { 'Cache-Control': 'public, max-age=3600' },
    }
  },
})
ACI provides the compiled content payload, fully validated, all references resolved, all overlays applied. Your code renders it into HTML. That’s the entire interface.

Code Capsules

When ACI builds your project, it produces a code capsule, a self-contained, portable artifact that includes your compiled code, the component registry, and the render function. The capsule is immutable and deduplicated by content. The same capsule is used everywhere: preview, staging, and production rendering. There’s no “preview build” vs “production build.” The only variable is the content payload.

Generally Available Frameworks

Astro

Full support. Static and server-rendered pages. Component islands with any UI framework (React, Vue, Svelte, Solid).

Next.js

Full support. Static generation (SSG) and server-side rendering (SSR). App Router and Pages Router.

SvelteKit

Full support. Static prerendering and server-side rendering. Form actions and progressive enhancement.
Each framework has its own build adapter that knows how to compile the project, extract the manifest, and invoke the render function in the framework’s native way. The content compiler and publish pipeline are framework-agnostic. They work with the manifest and capsule interface, not with framework internals.

What ACI Extracts

When ACI builds your code, it extracts a code manifest, a machine-readable summary of your project’s capabilities:
  • Components: Which content types your project can render, with their schemas
  • Routes: Which URL patterns your project handles
  • Assets: Static assets (images, fonts, CSS) with content-based hashes
  • Dependencies: Which components depend on which shared modules
The content compiler uses this manifest to validate content. If the manifest says your project has a Hero component that expects a headline string, the compiler enforces that constraint across every page that uses a Hero.
The frontend contract is intentionally minimal. A small config file, a registry, and a render function. Everything else (your build system, your CSS framework, your testing setup, your deployment scripts) stays exactly as it is.

Next: Framework Guides →