↑ ↓ to navigate
↵ to select
esc to close
Core Concepts Beginner

Content Modeling Guide

How collections, blueprints, entries, globals, navigations, forms, templates and assets fit together, with the 14 field types.

Overview

Airogel CMS stores content as structured data rather than free-form pages. You describe the shape of your content once with a blueprint. You group content of the same kind into a collection. Each piece of content is an entry. Site-wide values live in globals, menus in navigations, and visitor submissions arrive through forms. Templates turn all of this into HTML.

Building blockWhat it isUses a blueprint?
CollectionA group of entries with a URL pattern, templates and orderingYes, one or more
BlueprintA list of fields (the schema)—
EntryOne item in a collection: title, handle, URL and field valuesYes, one of its collection's
GlobalA named set of site-wide values, such as site title or social linksYes, exactly one
NavigationA menu of nested items that link to entries or URLsOptional, for extra fields on items
FormA visitor-facing form that saves submissions as entriesUses its collection's blueprint
TemplateA Liquid layout, page template or partialNo
AssetAn uploaded file (image, CSS, JavaScript, PDF…) referenced by pathNo

Blueprints and fields

A blueprint is an ordered list of fields. Each field has:

  • handle: the key used in templates and the API, unique within the blueprint (for example hero_image)
  • display: the label shown in the editor
  • type: one of the 14 field types below
  • options: settings for that type, such as the choices of an enumeration or the collection an entity field points to

There are 14 field types:

GroupTypes
Texttext, rich_text, raw_html
Mediaimage, gallery, video
Relationshipsentity, collection, template
Values and choicesnumber, toggle, enumerate
Structured datalist, dictionary

See the Field Types Reference for each type's options and value format.

A blueprint has one owner: a single collection, global or navigation. When you update a blueprint through the API or MCP, the fields list you send replaces the existing list. Fetch the current fields first and include every field you want to keep. Removing a field deletes the values stored in it.

Collections and entries

A collection lists the blueprints its entries may use. Each entry uses one of them, and you can switch an entry to another blueprint later. When you switch, values carry over for fields that have the same handle and type in both blueprints. All other values are dropped.

Every entry has these built-in attributes, in addition to its blueprint fields:

AttributeNotes
titleRequired when the entry is created
handleURL slug, used by :handle in routing. The API and MCP identify an entry within its collection by its handle.
publishedDefault true. Unpublished entries return 404 and are left out of listings, feeds and the sitemap.
published_atUsed for date routing (:year/:month/:day), feeds and date sorting
positionInteger sort key, default 0 (see Collections)
include_in_sitemapDefault true
Template, layout, routing_overrideOptional per-entry overrides of the collection's settings
content_pathThe entry's URL, generated from the routing pattern (read-only)

On a page, the current entry is available under its collection's handle:

<h1>{{ posts.title }}</h1>
<img src="{{ posts.hero_image }}" alt="">
{{ posts.body }}

Relationships between entries

  • Entity fields point at specific entries you choose, such as a post's author or a lesson's course. In templates, the referenced entry behaves like any other entry: {{ posts.author.title }}, {{ posts.author.content_path }}. An entity field can also build nested URLs, for example courses/:course/lessons/:handle (see Routing).
  • Collection fields pull in a filtered, ordered list of entries from another collection, such as "the five latest news posts" or "events tagged with this entry".
  • For more complex listings, use the {% query %} tag in a template. See Liquid Templates.

Globals

A global is a single record of site-wide values with its own blueprint. Every page can use it under the global's handle. New accounts start with a site global:

<title>{{ site.title }}</title>
<meta name="description" content="{{ site.description }}">

Manage globals under Content → Global Data, through the Globals API, or with MCP globals_save.

Navigations

A navigation is a menu of items, and items can nest. An item links either to an entry, in which case its URL follows the entry if the entry moves, or to any URL. A navigation can also have a blueprint, which adds extra fields to its items, such as an icon or a CSS class. In templates:

{% for item in navigation.main_navigation %}
  <a href="{{ item.url }}">{{ item.title }}</a>
  {% for child in item.children %}…{% endfor %}
{% endfor %}

See the Navigations API.

Forms

A form connects a public form on your site to a collection and one of that collection's blueprints. Each submission is saved as a new entry in that collection, and the blueprint's fields become the form's inputs. Forms can redirect or show a success message, email a notification, and screen spam with a honeypot or an automatic spam check. Render a form in a template with {% form_for form: "contact" %}. See Form For Tag and the Forms API.

Templates and assets

Templates are Liquid files identified by handle. Whether a template acts as a layout, a page template or a partial depends only on how it is used. A collection or entry names its template and layout, and {% render 'handle' %} includes a partial. Assets are uploaded files that templates reference by path, for example {{ 'site.css' | asset_url }}. See Liquid Templates, the Templates API and the Assets API.

Modeling tips

  • Create a separate collection for each kind of content that has its own URL shape or listing, such as pages, posts, people or products.
  • Use several blueprints within one collection when items share URLs but need different fields.
  • Use an entity field when an editor should pick specific items. Use a collection field when the list should update itself.
  • Keep handles lowercase with underscores, such as blog_posts or hero_image. Collection and global handles become Liquid variable names, and {{ blog-posts.title }} does not work. The MCP tools require snake_case handles for new collections, blueprints and globals.
  • Put values that appear on every page (contact details, social links, footer text) in a global, not in an entry.