Skip to main content
The manifest is a single JSON file at your project root that declares every collection in your CMS. It’s the source of truth for collection IDs, field schemas, on-disk paths, URL routes, and webhooks. The CMS panel reads this file to render forms; your build reads it to find entries; the AI reads it to know what’s editable.
The manifest is just a file in your repo — hiveku.cms.json at the root. You can edit it from the CMS panel’s Collection Manager, ask the AI to update it, or open it directly in the code editor.

File Location

your-project/
├── hiveku.cms.json        ← the manifest
├── content/
│   ├── blog/              ← entries for the "blog" collection
│   ├── authors/
│   └── products/
├── app/
└── package.json
The manifest must be at the repo root and named exactly hiveku.cms.json. The CMS panel won’t pick it up from a subdirectory.

Top-Level Schema

{
  "version": 1,
  "collections": [...],
  "webhooks": []
}
KeyTypeRequiredDescription
versionnumberYesSchema version. Always 1 for the current format. Bumped if a future release introduces breaking changes.
collectionsarrayYesThe list of collections. Order doesn’t affect behavior but does affect display order in the CMS panel’s collection picker.
webhooksarrayNoOutbound webhooks fired when entries change. Leave as [] if not used.

Per-Collection Schema

Each entry in collections looks like:
{
  "id": "blog",
  "name": "Blog Posts",
  "path": "content/blog",
  "format": "mdx",
  "slugFrom": "filename",
  "fields": [...],
  "routePattern": "/blog/{slug}",
  "defaultSort": "publishedAt desc"
}
KeyTypeRequiredDescription
idstringYesStable identifier used in references, AI tools, and API URLs. Lowercase, valid identifier characters only. Must be unique across the manifest.
namestringYesHuman-readable label shown in the CMS panel’s collection picker.
pathstringYesDirectory (relative to repo root) where entries are stored. By convention content/<id> or content/<plural-id>.
format"mdx" or "json"YesStorage format. mdx for content with a long-form body, json for purely structured data.
slugFrom"filename" or "field:<name>"NoHow to derive the slug. "filename" (default) uses the file’s basename; "field:title" derives from a field with auto-generated kebab-case.
fieldsarrayYesField definitions. See Field Types.
routePatternstringNoURL pattern using {slug} and other field placeholders. Leave off for collections that aren’t directly routed.
defaultSortstringNoDefault sort for the entry list, e.g. "publishedAt desc", "title asc".
singletonbooleanNoSet true for collections that should only ever have one entry (site settings, homepage hero). The list view becomes a direct edit.

Validation Rules

The CMS panel and the AI tools validate the manifest before saving. Common rules:
  • Unique id per collection — two collections can’t share an ID.
  • Valid identifiersid should match [a-z][a-z0-9-]*. Lowercase, no spaces, hyphens allowed.
  • Path must be a relative directory — no absolute paths, no .. traversal.
  • Exactly one isBody: true field per MDX collection — the body slot is required for MDX format. JSON collections must not have any isBody fields.
  • Field names are unique within a collection — no duplicate name values inside a single collection’s fields array.
  • References point at real collection IDs — a reference field’s collection value must match another collection’s id in the same manifest.
  • slugFrom: "field:<name>" requires a string field — and that field must be required: true.
If validation fails when saving from the CMS panel, you’ll get a 422 response with a list of errors. The Collection Manager surfaces them inline next to the offending field.

Full Example

Here’s a manifest covering a real site with blog posts, authors, products, and testimonials:
{
  "version": 1,
  "collections": [
    {
      "id": "authors",
      "name": "Authors",
      "path": "content/authors",
      "format": "json",
      "slugFrom": "field:name",
      "fields": [
        { "name": "name", "type": "string", "required": true },
        { "name": "bio", "type": "markdown" },
        { "name": "avatar", "type": "image" },
        { "name": "twitter", "type": "url" }
      ]
    },
    {
      "id": "blog",
      "name": "Blog Posts",
      "path": "content/blog",
      "format": "mdx",
      "slugFrom": "filename",
      "fields": [
        { "name": "title", "type": "string", "required": true },
        { "name": "excerpt", "type": "string" },
        { "name": "publishedAt", "type": "date", "required": true },
        { "name": "status", "type": "select", "options": ["draft", "published"], "default": "draft" },
        { "name": "author", "type": "reference", "collection": "authors", "required": true },
        { "name": "heroImage", "type": "image" },
        { "name": "tags", "type": "array", "items": "string" },
        { "name": "body", "type": "markdown", "isBody": true }
      ],
      "routePattern": "/blog/{slug}",
      "defaultSort": "publishedAt desc"
    },
    {
      "id": "products",
      "name": "Products",
      "path": "content/products",
      "format": "json",
      "slugFrom": "filename",
      "fields": [
        { "name": "name", "type": "string", "required": true },
        { "name": "sku", "type": "string", "required": true },
        { "name": "price", "type": "number", "required": true },
        { "name": "currency", "type": "select", "options": ["USD", "EUR", "GBP"], "default": "USD" },
        { "name": "inStock", "type": "boolean", "default": true },
        { "name": "images", "type": "array", "items": "image" },
        { "name": "description", "type": "markdown" },
        { "name": "category", "type": "string" }
      ],
      "routePattern": "/products/{slug}",
      "defaultSort": "name asc"
    },
    {
      "id": "testimonials",
      "name": "Testimonials",
      "path": "content/testimonials",
      "format": "json",
      "slugFrom": "filename",
      "fields": [
        { "name": "name", "type": "string", "required": true },
        { "name": "company", "type": "string" },
        { "name": "quote", "type": "string", "required": true },
        { "name": "avatar", "type": "image" },
        { "name": "featured", "type": "boolean", "default": false }
      ]
    },
    {
      "id": "site-settings",
      "name": "Site Settings",
      "path": "content/site-settings",
      "format": "json",
      "singleton": true,
      "fields": [
        { "name": "siteName", "type": "string", "required": true },
        { "name": "tagline", "type": "string" },
        { "name": "logo", "type": "image" },
        { "name": "primaryColor", "type": "color" }
      ]
    }
  ],
  "webhooks": [
    {
      "id": "rebuild-on-publish",
      "url": "https://api.hiveku.com/projects/your-project-id/rebuild",
      "events": ["entry.created", "entry.updated", "entry.deleted"],
      "collections": ["blog", "products"]
    }
  ]
}

Webhooks

Webhooks fire when CMS entries change. Each webhook entry takes:
KeyTypeDescription
idstringUnique webhook identifier
urlstringThe endpoint to POST to
eventsarraySubset of entry.created, entry.updated, entry.deleted, manifest.updated
collectionsarrayWhich collection IDs to listen to. Omit or use ["*"] for all
secretstringOptional shared secret; included as x-hiveku-signature HMAC header
Hiveku retries failed webhook deliveries up to 3 times with exponential backoff.

Editing the Manifest

Just describe what you want:
Add a "case-studies" collection with title, client, summary,
body, and a hero image. Route it at /case-studies/{slug}.
The AI reads the manifest, proposes the addition, and saves it after you confirm.

Versioning

Every edit to hiveku.cms.json is versioned the same way as any other file in your project, through the builder_code_versions system. Open the version history drawer for the manifest from the code editor to roll back schema changes.
Removing a field from the manifest doesn’t delete data from existing entries — the data stays in the file but won’t show in the form. Re-adding a field with the same name restores the editor for that data. Renaming a field, however, orphans the old data; ask the AI to write a migration if you need to rename safely.

What’s Next?

Field Types

Every supported field type with examples

Collections

Naming, format choice, and reusable patterns

Add a Collection

Three ways to add a new collection

Initialize Your CMS

Scaffold a manifest from scratch