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

Custom component

The escape hatch from the declarative page DSL into a freeform Vue component you author yourself.

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.

src/pages/reports.ts
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.

If the backend name and the registered component name disagree (after normalization), the slot renders a blank <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).