Custom component
CustomComponent is the escape hatch: when none of the built-in builders fit, it drops a component you authored — a real Vue SFC living in a frontend layer — into the page, while everything around it stays declarative. Reach for it only when the builders genuinely can't express the screen; the rest of the catalog needs no Vue.
What it renders
Whatever your Vue component renders. On the page it's an ordinary component node: the backend names it, the frontend looks the name up in its component registry and mounts your SFC in that slot, passing the backend .options(...) as props. If the name doesn't resolve, the slot renders an empty <div> — no error (see the footgun below).
Usage
CustomComponent(componentName) returns a ComponentBuilder, so it composes like any other component — attach it as a static field, set props with .options(...), nest it in a layout.
import { CustomComponent } from "@antelopejs-private/cms/interfaces/cms-base/custom";
@RegisterPage()
export class ReportsPage extends PageController("reports", {
displayName: "Reports",
category: pagesCategory,
}) {
static graph = CustomComponent("YourModuleGraphCanvas").options({
reportId: "main",
readOnly: false,
});
}
Your .vue receives those options as props, along with the page and route context the frontend provides to every component.
Options
The builder takes exactly one argument — the registered name of the component to mount — and carries no options of its own. Everything else flows through .options(props), whose object is passed verbatim as props: the real option surface is whatever props your SFC declares.
The name must resolve
The string must match a component your frontend layer registered. Resolution is normalized (lowercased, non-alphanumerics stripped) and built from the layer's prefix + the file's PascalCase name — e.g. a layer with prefix: "YourModule" and a file GraphCanvas.vue produces YourModuleGraphCanvas. The full rule, the .acms materialization, and the silent-empty-<div> failure mode are covered in Frontend layer.
<div> with no error. A blank custom pane is almost always this mismatch — check the prefix + filename first.Permissions
A custom component is a component on the page like any other: its full field/child position participates in the page's Auth & permissions, so you can gate it the same way. Authorization for any data your Vue fetches is enforced by the routes it calls, not by the component — use $authFetch/useFetchAuth for backend calls (see Auth requests & permissions).