[data-reveal]{opacity:1!important;transform:none!important}
CMS Interfaces

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 controllersPageController builds a controller class bound to a URL; @RegisterPage() records it, registers its permissions, and serves its layout.
  • Components that serialize — a ComponentBuilder produces 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:

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

SubpathContainsDocumented in
/pagePages, categories, modules, layouts, page extensions, dynamic menus, Nuxt layersPages and Modules
/componentComponent, ComponentBuilder, actions, watchesComponents
/permissionsThe permission registry and the permission computationPermissions
/permissions-resolverRegistering and running permission resolversPermissions
/guardsAuthUserWithPermission, AuthTenantOwner, AuthTenantMemberPermissions
/constantsSchema names and the default tenantTenancy
/dbThe Tenant, TenantMember, Role and UserInvite tables and modelsTenancy, Invites
/request-tenantgetRequestTenantIdTenancy
/tenant-scoped-modelTenantScopedModelTenancy
/tenant-accessTenant access gatesTenancy
/tenant-ownershipMembership and ownership writesTenancy
/data-controllersThe built-in members and roles data controllersTenancy
/invitesInviting a user into a tenantInvites
/hooksThe Hook enum, handlers and dispatchHooks
/tenant-exportThe tenant data export archive, contribution and manifest types, re-exported from /hooksHooks
/realtimePage topics, publishing and backend subscriptionRealtime
/quick-actionsCommand-palette entriesQuick Actions
/typesMaybePromise, the one shared type aliasPages 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