CMS Documentation
Overview
The cms interface is the core contract of the AntelopeJS DMS. It encodes one inversion: the backend declares the screen, as serializable data. A page is a controller class, its components are static fields holding builders, and the page's layout route returns the description a shared frontend renders. Adding an admin screen is a backend change.
Around that core the interface carries what an admin backend needs to be more than a renderer: hierarchical permissions derived from the page tree, multi-tenant data access scoped by the model handle, lifecycle hooks, realtime topics, and command-palette entries.
Consumers import from the subpaths of @antelopejs-private/cms/interfaces/cms. Two sibling interfaces shipped by the same module complete the picture and are referenced throughout these pages: cms-auth for authentication and the User table, and cms-base for the concrete component vocabulary (Form, TableView, Grid, the chart family) built on the component types documented here.
Key Features
- Pages as controllers —
PageControllerbuilds a controller class bound to a URL;@RegisterPage()records it, registers its permissions, and serves its layout. - Components that serialize — a
ComponentBuilderproduces data, not a live component, so one frontend renders every module's screens. - Categories and modules — a sidebar tree of nested categories, plus modules that own a whole branch under
/modules. - Dynamic navigation — providers that resolve extra menu entries per request, so one page can back an entry per project or workspace.
- Page extensions — inject components into a page owned by another module, permissioned in that page's own tree.
- Hierarchical permissions — ids derived from page, component and action, with a base set from roles and an effective set shaped by registered resolvers.
- Route guards — permission, tenant-member and tenant-owner decorators usable as parameter or property decorators.
- Tenancy in the handle — per-tenant schemas and model handles bound to one tenant, rather than a tenant column filtered on every query.
- Tenant access gates — one binary check that denies a tenant at every authorization surface at once.
- Invites — one call that either grants membership to an existing user or issues a token-bearing invite.
- Lifecycle hooks — typed events for tenants, members, invites and registrations, dispatched either to notify or to collect contributions.
- Realtime topics — bind a topic to a page, publish to whoever is on it, and subscribe from the backend to what others publish.
- Quick actions — contribute grouped, permission-gated entries to the command palette.
Dependencies
This interface relies on the following AntelopeJS packages:
- @antelopejs/interface-api - Controllers, route registration and request context.
- @antelopejs/interface-auth - The authentication decorator machinery the guards build on.
- @antelopejs/interface-core - Interface functions, registering proxies and decorator helpers.
- @antelopejs/interface-database-decorators - Table definitions, data models and model injection.
- @antelopejs/interface-data-api - Used by the
/data-controllerssubpath for the built-in members and roles controllers.
Quick Start
Declare a category, a page with a component, and the route that component fetches from:
import { Get } from "@antelopejs/interface-api";
import { GetModel } from "@antelopejs/interface-database-decorators";
import {
Category,
PageController,
RegisterPage,
pagesCategory,
} from "@antelopejs-private/cms/interfaces/cms/page";
import { KpiCard } from "@antelopejs-private/cms/interfaces/cms-base";
import { BookModel } from "./db";
export const catalog = Category("catalog", {
displayName: "Catalog",
icon: "i-ph-books",
category: pagesCategory,
});
@RegisterPage()
export class BooksPage extends PageController("books", {
displayName: "Books",
description: "Everything currently in the catalog",
icon: "i-ph-book-open",
category: catalog,
order: 1,
}) {
static inStockKpi = KpiCard({
title: "In stock",
icon: "i-ph-package",
fetchUrl: "/catalog/books/stats/in-stock",
valueFormat: "number",
});
@Get("/stats/in-stock")
async inStock() {
return { value: await GetModel(BookModel).countInStock() };
}
}
The page resolves at /catalog/books and its layout at /catalog/books/pagelayout. Its permission id is the chain of ids down from the root category — pages.catalog.books — with pages.catalog.books.inStockKpi registered underneath it.
Subpath Map
| Subpath | Contains | Documented in |
|---|---|---|
/page | Pages, categories, modules, layouts, page extensions, dynamic menus, Nuxt layers | Pages and Modules |
/component | Component, ComponentBuilder, actions, watches | Components |
/permissions | The permission registry and the permission computation | Permissions |
/permissions-resolver | Registering and running permission resolvers | Permissions |
/guards | AuthUserWithPermission, AuthTenantOwner, AuthTenantMember | Permissions |
/constants | Schema names and the default tenant | Tenancy |
/db | The Tenant, TenantMember, Role and UserInvite tables and models | Tenancy, Invites |
/request-tenant | getRequestTenantId | Tenancy |
/tenant-scoped-model | TenantScopedModel | Tenancy |
/tenant-access | Tenant access gates | Tenancy |
/tenant-ownership | Membership and ownership writes | Tenancy |
/data-controllers | The built-in members and roles data controllers | Tenancy |
/invites | Inviting a user into a tenant | Invites |
/hooks | The Hook enum, handlers and dispatch | Hooks |
/tenant-export | The tenant data export archive, contribution and manifest types, re-exported from /hooks | Hooks |
/realtime | Page topics, publishing and backend subscription | Realtime |
/quick-actions | Command-palette entries | Quick Actions |
/types | MaybePromise, the one shared type alias | Pages and Modules |
Symbols under an internal namespace are the wiring between this interface and its implementation. They are not part of the contract.
Documentation Sections
- Pages and Modules - Declare pages, group them into categories, own a branch of the sidebar with a module, and extend a page from another one
- Components - Build serializable components, declare actions and watches
- Permissions - Register permissions, compute a user's effective set, guard routes
- Tenancy - Schemas, the tenancy tables, tenant-scoped models and access gates
- Invites - Bring a user into a tenant by email
- Hooks - React to platform events and contribute to the tenant data export
- Realtime - Bind topics to pages, publish messages and subscribe to them
- Quick Actions - Contribute entries to the command palette