Architecture Overview
A technical overview of Airogel CMS: hosts, tenancy, the data model, how pages are served, identity layers and background processing.
System overview
Airogel CMS is a hosted, multi-tenant content management system. Each customer has one or more accounts. An account is an isolated workspace that holds a site's content, templates, files, domains, forms, events and constituent records. Every request, whether from the dashboard, the API, an AI assistant or a site visitor, is tied to exactly one account, and content never crosses between accounts.
The platform is a Ruby on Rails application backed by PostgreSQL, with Hotwire (Turbo and Stimulus) for the dashboard and Liquid for rendering customer sites.
Hosts
| Host | What it serves |
|---|---|
app.airogelcms.com | The dashboard: sign-up, billing, content editing, settings. It also hosts the OAuth authorization server used by API and MCP clients. |
api.airogelcms.com | The REST API (/v1/...) and the MCP server (/v1/mcp) |
auth.airogelcms.com | Central sign-in for constituents (site members and supporters) |
<subdomain>.airogelcms.com | Your public site on its platform subdomain |
| Your custom domains | Your public site, once each domain is verified. See Custom Domains. |
On a site host, the account is found from the verified custom domain or from the first label of the airogelcms.com subdomain. In the API, it comes from the account_id in the path. In MCP, it comes from the account_id argument each tool takes.
Data model
| Entity | Role |
|---|---|
| Account | The tenant workspace. It has users (staff) and a subscription. |
| Collection | A group of entries with a routing pattern, templates, ordering, an optional listing page and a feed |
| Blueprint → Blueprint fields | The schema: an ordered list of typed fields (14 types). Each blueprint has one owner: a collection, a global or a navigation. |
| Entry → Blueprint values | A content item. Each field value is stored with its type (text, image, entity…). |
| Content path | The resolved URL of an entry, unique within the account |
| Redirect / Redirect rule | Automatic redirects created when URLs change, and redirect rules you write |
| Template | A Liquid layout, page template or partial, identified by handle |
| Navigation → Navigation items | Menus of nested items that link to entries or URLs |
| Global | A site-wide set of values, available on every page |
| Form | A public form tied to a collection and blueprint. Each submission becomes an entry. |
| Asset / Video | Uploaded files and videos |
| Domain | A custom hostname, verified by DNS, used for the website and optionally for email |
| Context | Notes about the site (purpose, brand voice, guidelines) that AI assistants read before making changes |
| Event → Event tickets → Registrations | Scheduled events, their ticket types, and the people registered for them |
| Constituent | A CRM record for a person, with identifiers, consents, households, and role records such as registrations, memberships, donations and volunteering |
See Content Modeling for how the content entities relate to each other.
How a page is served
When a visitor requests a page on your site:
- The host is matched to your account.
- The path is checked against collection index routes (
/blog,/blog/page/2). - If no index route matches, the path is looked up in the account's content paths. If there is no match, automatic redirects are checked.
- Two gates apply to the entry.
/is served only by a collection withroot_routingon, and unpublished entries return 404. - The entry's template (or its collection's template) is rendered with Liquid. The entry, your globals, navigations and events are available as variables.
- That output becomes
content_for_layoutinside the layout. SEO tags (meta, Open Graph, JSON-LD, feed links) and the CMS form scripts are injected throughcontent_for_header. - If nothing matched, your redirect rules are tried. Only after that does the site return a 404 page in your
themelayout.
Other paths on the site host are served separately: /sitemap.xml, /robots.txt, feeds, uploaded assets, form submissions (/cms/<form>/submit) and the member portal (/portal). Every page is also available as Markdown when requested with a .md extension (for example /about.md). See Routing for the details.
Ways to change content
- Dashboard at
app.airogelcms.com. - REST API at
https://api.airogelcms.com/v1, using an API token or an OAuth access token. See API Overview. - MCP server at
https://api.airogelcms.com/v1/mcp(Streamable HTTP), for AI assistants. It supports OAuth 2.0 with PKCE and dynamic client registration, and scopes that limit which tools a client can see. It covers more than the REST API: domains, redirect rules, events, search, theme validation and previews are MCP-only. See MCP Integration. - Liquiditor, a local theme preview tool that syncs with your account. See Liquiditor.
The REST API and MCP use the same services underneath. Saving a collection, blueprint, global, navigation, template or entry is keyed by its handle, so saving again with the same handle updates the existing record instead of creating a duplicate.
Identity: staff and constituents
Airogel CMS keeps two kinds of people separate:
- Users are your staff. They sign in to the dashboard, belong to one or more accounts, and are the only people who can edit content or manage billing.
- Constituents are the people your organisation serves, such as members, donors, volunteers and attendees. They never get dashboard access.
Constituent identity has two layers. A shared platform layer (a principal with verified email addresses or phone numbers) handles sign-in once, at auth.airogelcms.com. That layer belongs to the platform, not to any account. Each account then links the sign-in to its own constituent record, which holds that account's CRM data, consent and role history. The same person can be a constituent of several organisations, and each organisation sees only its own record. See Constituents & CRM.
Background work and real-time updates
Background jobs, caching and live updates all run on PostgreSQL, through Solid Queue, Solid Cache and Solid Cable. There is no separate Redis layer. Work that happens after a save runs as a background job. Examples include registering a newly verified domain for HTTPS, sending form notifications, spam-checking submissions, and processing uploaded video.
Search, feeds and SEO
- Entries are indexed with PostgreSQL full-text search over title, handle and text, rich-text and raw-HTML fields. Search is available through the MCP
search_querytool. See Full-Text Search. - Feed-enabled collections publish RSS 2.0 and JSON Feed. See Feeds.
- Each page gets generated meta tags, Open Graph and Twitter tags, and JSON-LD structured data. The
schema_typecomes from the collection and defaults toWebPage.
Billing and access
Every account needs an active subscription. Without one, the dashboard redirects to the pricing page, the REST API returns 402, and MCP tools return a payment_required error. Plan tiers gate some dashboard features, such as AI chat and Creator Mode, but the API and MCP are available on every plan. See Billing.