Skip to content

Extending Rebase

Rebase offers roughly a dozen extension mechanisms — plugins, slots, component overrides, entity views, actions, custom fields, and more. Each one targets a different scope (app-wide, per-collection, per-entity, per-property) and a different part of the UI.

This guide helps you pick the right mechanism for your use case, then links to the detailed reference for each.

Everything here is the admin panel. For the server — narrowing a read, adding a route, embedding the driver in your own process, rebase eject — see Rebase doesn’t do X, which is the same kind of table for the backend.

I want to… Mechanism Scope Reference
Replace the app bar components (Shell.AppBar) app Component Overrides
Replace the login page components (Auth.LoginView) app Component Overrides
Replace the home page components (HomePage) app Component Overrides
Change how one collection’s form looks entirely formView collection below
Swap one component inside one collection collection.components collection Component Overrides
Set default component overrides for all collections components (collection-scoped names) app Component Overrides
Add a button to the collection toolbar collection Actions collection Entity Actions
Inject UI at a collection toolbar slot collection.actions slot app/plugin Slots
Add a computed column to a table additionalFields collection Additional Columns
Add a custom field widget for a property type propertyConfigs property type Custom Fields
Add an entity tab entityViews entity Entity Views
Render one collection’s rows a different way admin.customViews collection below
Add a row/context action or entity button entityActions entity Entity Actions
Put a figure on a collection’s home-page card home.card.widget slot app/plugin Slots
Inject UI at a specific chrome location slots app/plugin Slots
Ship several extensions as one installable unit plugins app Plugins
Style the thing I just built @rebasepro/ui + theme tokens any Styling Custom UI

Scope: app.

A plugin bundles collections, views, component overrides, slot contributions, auth, data sources, providers, hooks, and lifecycle callbacks into a single installable unit. All other mechanisms listed here can be contributed through a plugin’s interface.

→ Plugins reference

Scope: app (contributed per-slot).

Slots are named UI extension points scattered throughout the CMS chrome. You register a React component targeting a slot name, and it renders at that location. There are 27 slots covering the home page, navigation, collection views, forms, entity rows, form fields and the app bar — and every one of them is rendered.

→ Slots reference

Scope: app-level defaults or per-collection.

Two modes: Eject (full replacement) or Wrap (augment the original).

19 overridable component names in two tiers:

App-only (7):

  • Shell.AppBar
  • Shell.Drawer
  • Shell.DrawerNavigationItem
  • Shell.DrawerNavigationGroup
  • HomePage
  • HomePage.CollectionCard
  • Auth.LoginView

Collection-scoped (12):

  • Collection.View
  • Collection.Table
  • Collection.Card
  • Collection.EmptyState
  • Collection.Actions
  • Collection.FilterField
  • Entity.Form
  • EditView.FormActions
  • DetailView
  • Entity.SidePanel
  • EntityPreview
  • Entity.MissingReference

Precedence: Collection-level components override app-level defaults for the same component name (simple object spread — collection values overwrite global values). App-only component names (Shell.*, HomePage, Auth.*) can only be overridden at the <Rebase> level.

→ Component Overrides

Scope: entity (adds tabs).

Custom views that appear as tabs in the entity detail page. Can be defined globally on <Rebase> or per-collection.

→ Entity Views

Scope: entity.

Custom action buttons on individual entities (publish, archive, clone, etc.). Can be defined globally or per-collection.

→ Entity Actions

Scope: collection.

Toolbar-level React components that receive CollectionActionsProps (selected entities, table controller, collection context). Rendered in the collection toolbar alongside built-in actions.

Relationship with collection.actions slot: Both are additive — Actions components render first in the toolbar, then slot contributions from collection.actions. They do not replace each other.

→ Entity Actions — Collection Actions

Scope: collection (adds a view mode).

A map, a calendar, a gallery, a timeline — another rendering of the same rows, offered in the collection’s view switcher beside List, Table, Cards and Board.

// collection config
admin: {
customViews: [
{ key: "map", name: "Map", icon: "Map", Builder: MapView }
],
enabledViews: ["table", "map"],
defaultViewMode: "map"
}

Or register the component once and name it by key, which is also what makes it selectable from the collection editor:

<RebaseCMS
collections={collections}
collectionViews={[{ key: "map", name: "Map", icon: "Map", Builder: MapView }]}
/>
admin: { customViews: ["map"] }

Builder receives the live tableController, so the view inherits the collection’s filters, the search box, sorting, pagination, permission checks and the entity side panel — that is the whole reason to declare one instead of building an AppView:

function MapView({ tableController, onEntityClick }: CollectionCustomViewParams) {
return <MapCanvas
markers={tableController.data.map(e => e.values.location)}
onMarkerClick={i => onEntityClick?.(tableController.data[i])}
/>;
}

Choosing the view updates ?__view=, survives a reload, and persists per user. Declaring one is enough to offer it — enabledViews only needs setting when you want to take built-ins away. With a single entry the switcher is hidden.

This is not a way to build a view spanning several collections. A view mode is another rendering of one collection’s query. If your component ignores tableController and fetches four tables of its own, it wants to be an AppView — the toolbar above it, with its search box and its record count, would be describing a query it does not render.

Scope: collection.

Replaces the entire default entity form with a custom component. Set on a collection definition:

const collection = {
slug: "products",
admin: {
formView: {
Builder: MyCustomProductForm,
includeActions: true // Save and Discard in the bar (default: true)
}
}
};

Use when you need a completely custom layout for one collection’s entity editing experience. For smaller tweaks, prefer collection.components with Entity.Form override instead.

The Builder is rendered inside the record’s form and receives its live formContext: write with formContext.setFieldValue, and the bar’s Save stores the record. Where the record cannot be edited — the read-only detail view, or a user without edit permission — formContext.disabled is true and writes throw. Set includeActions: false if your Builder saves on its own through formContext.submit().

Scope: collection.

Computed/virtual columns displayed in the collection table. These don’t correspond to stored properties — they’re calculated at render time.

→ Additional Columns

Scope: property type.

Custom field widgets for specific property types, providing custom form fields and preview components.

→ Custom Fields

If the thing you want to change is what the server does rather than what the panel shows, this is the wrong page. The server has its own ladder:

I want to… Rung Reference
Narrow which rows a read returns beforeQuery callback Extending the server
Redact a value on the way out afterRead callback Callbacks
Add an endpoint of my own custom function Custom Functions
Make search find substrings and fold accents search.mode: "hybrid" Search
Own the server process custom server, then rebase eject Extending the server

→ Rebase doesn’t do X

  • collection.components applies over global components inside that collection. A collection replacement replaces both; Since 0.25 a collection wrap: true override wraps the global override when there is one (on 0.24 it wraps the built-in, and the global override is skipped). See Component Overrides.
  • Collection Actions and collection.actions slot are additive — Actions render first, then slot contributions.
  • Collection-level entityActions and entityViews extend (not replace) global ones.
  • Plugins apply in the order of the plugins array, not by key. Slot contributions render by their order (lower first, 50 by default), and ties keep that order. Since 0.25 Field wrappers from several plugins compose in that order, the first plugin’s innermost; on 0.24 only the last wrapper rendered. See Plugins.