Introduction
Overview
The base domain of @antelopejs/interface-dms is the component vocabulary of the DMS: forms, tables, charts and cards, layout containers, trees, the data types behind every field, and the shared prop types they all draw from.
Every component here is a builder. Form({...}), TableView(controller, {...}) and ChartLine({...}) do not render anything — they return a ComponentBuilder from @antelopejs/interface-dms/component, which is a serializable description of a component: its name, its options, and its children. You assign that description to a static field of a page class, and the frontend reads the page's tree and draws it. The options you set are therefore data, and the components that need data are given a fetchUrl and a submitUrl pointing back at routes you declare on the same page or on a data controller.
Two consequences shape the whole domain. First, a component's contract is its props interface: what you can express is exactly what the props allow, which is why this reference documents them field by field. Second, anything the frontend must receive has to survive serialization, so a builder that accepts a nested Component — a modal target, a kanban card, a chart inside a card — stores its serialized form instead.
The DMS documentation carries task-shaped chapters on the same components, organised around what you are building. This folder is the contract behind them: the exact symbol names, option fields and return types.
Subpath Map
@antelopejs/interface-dms/base is the barrel over the modules below, and re-exports most of them. The ones marked as not in the barrel are imported from their own subpath. Every row is a subpath of @antelopejs/interface-dms/base.
| Subpath | Holds | In the root barrel | Documented in |
|---|---|---|---|
types | Base props, colours, tones (TONES, Tone, ICON_TONES, IconTone), sizes, buttons, action targets, row-action rules, guards, watch actions, enums | yes | Shared Types |
form | Form, the field and group shapes, FormComponents, FormEvents, the schema helpers | yes | Forms |
table-view | TableView, @Column, TableViewRoutes, guards, row actions | yes | Tables |
chart | Chart builders, series and point shapes, chart props | yes | Charts and Widgets |
chart-card | ChartCard | yes | Charts and Widgets |
kpi-card | KpiCard | yes | Charts and Widgets |
top-list-card | TopListCard | yes | Charts and Widgets |
period-selector | PeriodSelector | yes | Charts and Widgets |
live-toggle | LiveToggle | yes | Display Blocks |
grid | Grid, GridRow | yes | Layout and Containers |
stack | HStack, VStack, Spacer | yes | Layout and Containers |
tab | Tab | yes | Layout and Containers |
guard | Guard | yes | Layout and Containers |
layouts | DefaultLayout, FormPageLayout, SettingsLayout, EmptyLayout | yes | Layout and Containers |
placeholder | Placeholder | yes | Layout and Containers |
display | BlockLinkAction, BlockItemsSource, BlockEmptyText | yes | Display Blocks |
stat-group | StatGroup | yes | Display Blocks |
key-value-list | KeyValueList | yes | Display Blocks |
nav-card-grid | NavCardGrid | yes | Display Blocks |
empty-state | EmptyState | yes | Display Blocks |
banner | Banner | yes | Display Blocks |
card | Card | yes | Display Blocks |
code-block | CodeBlock | yes | Display Blocks |
custom | CustomComponent | no | Layout and Containers |
data-types | DataType, the registration decorators, DefaultDataTypes, DefaultDataCompareTypes, StatusType | no | Data Types |
searchable | Searchable, SearchableMeta | yes | Helpers |
export-jobs | runExportJob and the export-job lifecycle | yes | Helpers |
tenant-export-archive | startTenantExportJob, buildTenantExportArchive | yes | Helpers |
helpers/file-refs | File and image reference tracking | no | Helpers |
helpers/archive-mode-helpers | applyArchiveModeDefaultRules | no | Helpers |
Within types, four modules are outside that subpath's barrel and are imported from types/action-target, types/row-action, types/row-action-operators and types/guards; the guard types and RowActionRule are also re-exported by table-view.
Key Features
- Builders that produce data — Every component function returns a
ComponentBuilder, so a page's UI is a plain value you can factor, reuse and compose with.child(). - Forms from typed fields — A field names a
DataType, and the type supplies both the input component and the Zod schema;Formcompiles the field list into one schema and ships its JSON Schema form with the component. - Tables from data controllers —
TableViewreads a controller's data-api metadata and its@Columndeclarations to build the columns, thenew/edit/viewforms, and the permission-carrying actions in one call. - Server-enforced row rules and guards — Row-action rules are a small algebra evaluated on both sides, and guards run inside the mutating routes, so what the row menu offers is what the server accepts.
- A chart and widget set with a shared period scope — Thirteen chart types plus KPI, chart and top-list cards; one
PeriodSelectorid ties them to the same range and comparison. - Layout without a frontend build — Grids, stacks, tabs and page layouts arrange components, and
CustomComponentnames a Vue component when the vocabulary runs out. - An extensible data-type registry —
@RegisterDataTypeand@RegisterDataCompareModeadd your own types and filter operators to the catalogue the forms, columns and filters draw from. - Shared prop vocabulary — Colours, sizes, HTTP methods, action targets, readonly behaviour and watch actions are declared once in
typesand reused by every component.
Dependencies
This interface relies on the following AntelopeJS packages:
- @antelopejs/interface-api - Request context, controller metadata and route parameters.
- @antelopejs/interface-api-util -
assertfor failing a route with an HTTP status. - @antelopejs/interface-core - Metadata storage, decorator factories, interface functions and logging.
- @antelopejs/interface-data-api - Data controllers, default routes, list parameters and field metadata.
- @antelopejs/interface-database - The value proxies compare modes build their filters from.
- @antelopejs/interface-database-decorators - Models and the localization modifier.
- @antelopejs/interface-file-storage - Upload constraints, staged-key promotion and file deletion behind the file and image types.
- zod and zod-to-json-schema - Field validation schemas and their JSON Schema form.
It also builds on other domains of the same package: /component for Component and ComponentBuilder, /page for the page a component is registered on, /permissions for the action permissions a table view declares, and /auth for the authenticated user its routes receive.
Quick Start
A page declaring one component. The Form builder describes the fields; the two routes on the same class serve and accept the values. Define the backing model first; SettingsModel is application code, not a DMS export.
import {
BasicDataModel,
Field,
RegisterTable,
Table,
} from "@antelopejs/interface-database-decorators";
export const SETTINGS_SCHEMA = "example_settings";
export const SETTINGS_ROW_ID = "module";
@RegisterTable("settings", SETTINGS_SCHEMA)
export class Settings extends Table {
@Field("string") declare _id: string;
@Field("boolean") declare enabled: boolean;
@Field("number") declare retentionDays: number;
}
export class SettingsModel extends BasicDataModel(Settings, "settings") {}
The page edits one module-wide record, so restrict it to platform owners. It returns defaults before the first save and upserts only SETTINGS_ROW_ID, rather than updating every row in the table.
import { Get, JSONBody, Post } from "@antelopejs/interface-api";
import { assert } from "@antelopejs/interface-api-util";
import { GetModel } from "@antelopejs/interface-database-decorators";
import {
PageController,
pagesCategory,
RegisterPage,
} from "@antelopejs/interface-dms/page";
import { DefaultDataTypes } from "@antelopejs/interface-dms/base/data-types";
import { Form, formSchema } from "@antelopejs/interface-dms/base/form";
import { DefaultLayout } from "@antelopejs/interface-dms/base/layouts";
import { HttpMethod } from "@antelopejs/interface-dms/base/types";
import { AuthOwnerOnly } from "@antelopejs/interface-dms/auth";
import { SettingsModel, SETTINGS_ROW_ID } from "./db";
@RegisterPage()
@AuthOwnerOnly()
export class SettingsPage extends PageController(
"settings",
{
urlSlug: "settings",
displayName: "Settings",
description: "Module configuration",
icon: "i-ph-gear",
category: pagesCategory,
},
DefaultLayout(),
) {
static form = Form({
title: "Settings",
fetchUrl: "/settings/",
submitUrl: "/settings/",
submitUrlMethod: HttpMethod.post,
fields: [
{
id: "enabled",
label: "Enabled",
type: new DefaultDataTypes.BooleanType(),
},
{
id: "retentionDays",
label: "Retention (days)",
type: new DefaultDataTypes.NumberType({ min: 0 }),
required: true,
},
],
});
settingsModel = GetModel(SettingsModel);
@Get("/")
async read() {
return await this.settingsModel.get(SETTINGS_ROW_ID)
?? { enabled: false, retentionDays: 0 };
}
@Post("/")
async write(@JSONBody() body: unknown) {
const result = formSchema(SettingsPage.form).safeParse(body);
assert(result.success, 400, "Invalid settings");
await this.settingsModel.table.insert({
_id: SETTINGS_ROW_ID,
enabled: result.data.enabled ?? false,
retentionDays: result.data.retentionDays,
}, { conflict: "update" });
}
}
Import the page and provision the schema from your module's entry file. Merge this into an existing start() if your module already has one:
import "./settings-page";
import { RegisterSchema } from "@antelopejs/interface-database-decorators";
import { SETTINGS_SCHEMA } from "./db";
export async function start(): Promise<void> {
await RegisterSchema(SETTINGS_SCHEMA);
}
The page registers itself at import time, and its routes are mounted under the page's slug — which is why the form fetches from and submits to /settings/. Form serializes the field descriptions and JSON Schema for the frontend; the custom write route must still validate the request on the server, as the formSchema call does here. For per-tenant settings, use a tenant-scoped schema and model instead of this module-wide record.
Documentation Sections
- Shared Types - Base props, colours, sizes, action targets, row-action rules, guards and the small enums.
- Forms - The
Formbuilder, fields and groups, input components and the validation schema. - Tables - Table views over a data controller: columns, routes, row actions, guards, displays and generated forms.
- Charts and Widgets - Chart types and props, chart cards, KPI cards, top lists and the period selector.
- Layout and Containers - Grids, stacks, tabs, the guard, page layouts, the placeholder and the custom-component escape hatch.
- Data Types - The
DataTypecontract, the registries, the default catalogue and a custom type. - Helpers - Searchable columns, export jobs, file references and the archive-mode defaults.
External Identities
An external identity binds an account a user owns on a login provider — GitHub, Google, whichever the deployment configures — to a `User` row, so that signing in through that provider resolves to the same account…
Shared Types
The `types` subpath holds the vocabulary every other part of the `base` domain is built from: the base props interface every component's props extend, the colour and size scales, the action targets a button or a row…