Admin extensions customize the Webiny Admin application. There are three main categories: white-labeling (logos, titles, theme colors), custom data list columns (adding columns to content entry tables), and custom page-type forms (custom form fields for Website Builder page types). All are React components registered via <Admin.Extension> in webiny.config.tsx.
YOU MUST include the full file path with the .tsx extension in every src prop. For example, use src={"/extensions/MyAdminExtension.tsx"}, NOT src={"/extensions/MyAdminExtension"}. Omitting the file extension will cause a build failure.
// extensions/AdminBranding/AdminTheme.tsx
import React from "react";
import { AdminConfig } from "webiny/admin/configs";
const { Theme } = AdminConfig;
const AdminTheme = () => {
return (
<AdminConfig.Public>
<Theme.Color palette={"primary"} color={"purple"} />
<Theme.Color palette={"secondary"} color={"green"} />
</AdminConfig.Public>
);
};
export default AdminTheme;
palette -- "primary", "secondary", "neutral", etc.color -- any CSS color value: named colors, hex ("#6B46C1"), or RGB.// extensions/AdminBranding/AdminTitleLogo.tsx
import React from "react";
import { AdminConfig } from "webiny/admin/configs";
import squareLogo from "./logo.png";
import horizontalLogo from "./logo.png";
const { Title, Logo } = AdminConfig;
const AdminTitleLogo = () => {
return (
<AdminConfig.Public>
<Title value={"ACME Corp"} />
<Logo
squareLogo={<img src={squareLogo} alt={"ACME Corp"} />}
horizontalLogo={<img src={horizontalLogo} alt={"ACME Corp"} />}
/>
</AdminConfig.Public>
);
};
export default AdminTitleLogo;
Register both:
<Admin.Extension src={"/extensions/AdminBranding/AdminTheme.tsx"} />
<Admin.Extension src={"/extensions/AdminBranding/AdminTitleLogo.tsx"} />
| Component | Purpose |
|---|---|
<Theme.Color palette="..." color="..." /> |
Set theme color palette |
<Title value="..." /> |
Set the Admin app title |
<Logo squareLogo={...} horizontalLogo={...} /> |
Set square and horizontal logos |
All must be wrapped in <AdminConfig.Public>.
Add custom columns to the content entry list view in the Admin UI. Columns can be restricted to specific content models.
// extensions/contactSubmission/EmailEntryListColumn.tsx
import React from "react";
import { ContentEntryListConfig } from "webiny/admin/cms/entry/list";
const { Browser } = ContentEntryListConfig;
// Custom cell component for the Email Type column
interface ContactSubmissionTableRow {
values: {
emailType: "work" | "personal";
};
}
export const EmailTypeCell = () => {
const { useTableRow, isFolderRow } = ContentEntryListConfig.Browser.Table.Column;
const { row } = useTableRow<ContactSubmissionTableRow>();
if (isFolderRow(row)) {
return <>{"-"}</>;
}
const emailType = row.data.values.emailType;
return emailType === "work" ? <>{"Business"}</> : <>{"Personal"}</>;
};
// Main extension component
const EmailEntryListColumn = () => {
return (
<ContentEntryListConfig>
{/* Simple column using path (no custom cell needed) */}
<Browser.Table.Column
name={"email"}
after={"name"}
path={"values.email"}
header={"Email"}
modelIds={["contactSubmission"]}
/>
{/* Custom cell column */}
<Browser.Table.Column
name={"emailType"}
after={"email"}
header={"Email Type"}
modelIds={["contactSubmission"]}
cell={<EmailTypeCell />}
/>
</ContentEntryListConfig>
);
};
export default EmailEntryListColumn;
Register:
<Admin.Extension src={"/extensions/contactSubmission/EmailEntryListColumn.tsx"} />
| Prop | Type | Description |
|---|---|---|
name |
string |
Unique column identifier |
header |
string |
Column header text |
path |
string |
Dot-path to the data field (e.g., "values.email") -- for simple columns |
cell |
ReactElement |
Custom React component for complex rendering |
modelIds |
string[] |
Restrict column to specific content models |
after |
string |
Position this column after another column by name |
Inside a custom cell component:
useTableRow<T>() -- access the full row data, typed with your interfaceisFolderRow(row) -- check if the current row is a folder (return placeholder content)Create custom forms for Website Builder page types using Webiny's form components:
// extensions/customPageTypes/RetailPageForm.tsx
import React from "react";
import { PageListConfig } from "webiny/admin/website-builder/page/list";
import { Bind, UnsetOnUnmount, validation } from "webiny/admin/form";
const { PageType } = PageListConfig;
export const RetailPageForm = () => {
const form = useForm();
return (
<>
{/* Mount the default page form fields. */}
<PageType.Language />
<PageType.Title />
<PageType.Path />
{/* Add custom fields.*/}
<Grid.Column span={12}>
<UnsetOnUnmount name={"extensions.customField"}>
<Bind name={"extensions.customField"} validators={[validation.create("required")]}>
<Input label={"Custom Field"} />
</Bind>
</UnsetOnUnmount>
</Grid.Column>
</>
);
};
| Component / Hook | Import | Purpose |
|---|---|---|
Bind |
"webiny/admin/form" |
Bind a form field to a name path |
useForm() |
"webiny/admin/form" |
Access the form API (getValue, setValue) |
validation |
"webiny/admin/form" |
Create validators (validation.create("required")) |
UnsetOnUnmount |
"webiny/admin/form" |
Clear the field value when the component unmounts |
Grid.Column |
"webiny/admin/ui" |
Layout grid column (span={12} for full width) |
Input |
"webiny/admin/ui" |
Text input field |
Select |
"webiny/admin/ui" |
Dropdown select with options |
FormApi |
"webiny/admin/form" |
Type for the form API object |
Admin extensions can also add custom plugins to the Lexical rich text editor used in both the Headless CMS and the Website Builder. These are registered as <Admin.Extension> and use imports from "webiny/admin/lexical", "webiny/admin/cms/lexical", and "webiny/admin/website-builder/lexical".
White-label import: import { AdminConfig } from "webiny/admin/configs";
Data list import: import { ContentEntryListConfig } from "webiny/admin/cms/entry/list";
Form imports: import { Bind, useForm, validation } from "webiny/admin/form";
UI imports: import { Grid, Input, Select } from "webiny/admin/ui";
Register: <Admin.Extension src={"/extensions/MyAdminExtension.tsx"} />
Develop: yarn webiny watch admin
Deploy: yarn webiny deploy admin
webiny-project-structure -- How to register Admin extensionswebiny-full-stack-architect -- Full-stack extension skeleton and registrationwebiny-admin-architect -- Admin-side architecture patterns (headless + presentation features)