Webiny-js webiny-admin-ui-extensions
git clone https://github.com/webiny/webiny-js
T=$(mktemp -d) && git clone --depth=1 https://github.com/webiny/webiny-js "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/user-skills/admin/ui-extensions" ~/.claude/skills/webiny-webiny-js-webiny-admin-ui-extensions && rm -rf "$T"
skills/user-skills/admin/ui-extensions/SKILL.mdAdmin UI Extensions
TL;DR
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
extension in every .tsx
prop. For example, use src
src={"/extensions/MyAdminExtension.tsx"}, NOT src={"/extensions/MyAdminExtension"}. Omitting the file extension will cause a build failure.
White-Labeling
Theme Colors
// 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"
, etc."neutral"
-- any CSS color value: named colors, hex (color
), or RGB."#6B46C1"
Logo and Title
// 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"} />
Available AdminConfig Components
| Component | Purpose |
|---|---|
| Set theme color palette |
| Set the Admin app title |
| Set square and horizontal logos |
All must be wrapped in
<AdminConfig.Public>.
Custom Data List Columns
Add custom columns to the content entry list view in the Admin UI. Columns can be restricted to specific content models.
Full Example: Email Columns for Contact Submissions
// 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"} />
Column Props Reference
| Prop | Type | Description |
|---|---|---|
| | Unique column identifier |
| | Column header text |
| | Dot-path to the data field (e.g., ) -- for simple columns |
| | Custom React component for complex rendering |
| | Restrict column to specific content models |
| | Position this column after another column by name |
Custom Cell Hooks
Inside a custom
cell component:
-- access the full row data, typed with your interfaceuseTableRow<T>()
-- check if the current row is a folder (return placeholder content)isFolderRow(row)
Custom Page-Type Forms
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> </> ); };
Form Components Reference
| Component / Hook | Import | Purpose |
|---|---|---|
| | Bind a form field to a name path |
| | Access the form API (, ) |
| | Create validators () |
| | Clear the field value when the component unmounts |
| | Layout grid column ( for full width) |
| | Text input field |
| | Dropdown select with options |
| | Type for the form API object |
Lexical Editor Plugins
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".
Quick Reference
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
Related Skills
-- How to register Admin extensionswebiny-project-structure
-- Full-stack extension skeleton and registrationwebiny-full-stack-architect
-- Admin-side architecture patterns (headless + presentation features)webiny-admin-architect