Custom Pages
A custom page lets you add your own page to the CMS, next to the Contents, Assets and Editorial Workflow pages. It can show a dashboard built with a React component, embed another web page, such as your analytics or deployment status, or simply link to an external site.
Overview
To register a custom page, use the registerCustomPage method on the CMS object:
CMS.registerCustomPage(definition);Parameters
definition(object, required): The page definition, with the following properties:id(string, required): A unique identifier for the page, consisting of alphanumeric characters, hyphens and underscores. The page is opened at#/pages/{id}, so you can link to it directly. Registering a page with the same ID again replaces the previous one in place.label(string, required): The label of the page, displayed as the page title and as the tooltip of the page’s button.icon(string, optional): The name of a Material Symbols icon displayed on the page’s button, e.g.monitoring. Defaults toextension.component(React component): A React component rendering the page content. The component receives no props. You can write it with HTM, JSX orh()calls.url(string): The URL of a web page to show. A relative URL is resolved against the current page URL. OnlyhttpandhttpsURLs are supported.newTab(boolean, optional): Whether to open theurlin a new browser tab instead of embedding it in the CMS. Defaults tofalse. Can only be used withurl.
Either component or url must be given, but not both. An invalid definition throws a TypeError.
Where Pages Appear
On desktop, custom pages are listed in the global toolbar after the built-in pages, in the order of registration, and can be opened with the Alt+1–9 keyboard shortcuts along with the built-in pages. A page opening in a new tab is shown as a separate button after the page buttons.
On mobile, the bottom navigation has little room, so custom pages are listed in the Pages section of the Menu page instead.
Pages can be registered before or after the CMS is initialized. A page registered later appears right away, and a link to #/pages/{id} shows the page as soon as it’s registered.
Examples
React Component
The following page greets the user and counts their clicks, using the useState hook. A component can use any hook taken from CMS.React.
const { useState } = CMS.React;
const Dashboard = () => {
const [count, setCount] = useState(0);
return html`
<div style="padding: 16px">
<h3>Welcome back!</h3>
<p>You’ve clicked the button ${count} times.</p>
<button type="button" onClick=${() => setCount(count + 1)}>Click Me</button>
</div>
`;
};
CMS.registerCustomPage({
id: 'dashboard',
label: 'Dashboard',
icon: 'dashboard',
component: Dashboard,
});const { useState } = CMS.React;
const Dashboard = () => {
const [count, setCount] = useState(0);
return (
<div style={{ padding: 16 }}>
<h3>Welcome back!</h3>
<p>You’ve clicked the button {count} times.</p>
<button type="button" onClick={() => setCount(count + 1)}>
Click Me
</button>
</div>
);
};
CMS.registerCustomPage({
id: 'dashboard',
label: 'Dashboard',
icon: 'dashboard',
component: Dashboard,
});const { useState } = CMS.React;
const Dashboard = () => {
const [count, setCount] = useState(0);
return h(
'div',
{ style: { padding: 16 } },
h('h3', null, 'Welcome back!'),
h('p', null, `You’ve clicked the button ${count} times.`),
h('button', { type: 'button', onClick: () => setCount(count + 1) }, 'Click Me'),
);
};
CMS.registerCustomPage({
id: 'dashboard',
label: 'Dashboard',
icon: 'dashboard',
component: Dashboard,
});The page area has no padding, so your component can fill it, e.g. with a full-size chart. Add your own padding as needed.
Embedded Web Page
To show another web page within the CMS, provide its URL. The page is embedded in an iframe that fills the page area.
CMS.registerCustomPage({
id: 'analytics',
label: 'Analytics',
icon: 'monitoring',
url: 'https://plausible.io/share/example.com?auth=XXXXXXXX',
});A relative URL is resolved against the CMS admin page URL, so a page of your own site can be embedded as well:
CMS.registerCustomPage({
id: 'style-guide',
label: 'Style Guide',
icon: 'palette',
url: '/style-guide/',
});Embedding restrictions
Many sites prevent their pages from being embedded in an iframe with the X-Frame-Options or Content-Security-Policy response header. Such a page appears blank or shows an error in the CMS. Use the newTab option for these sites instead.
Security note
A page embedded from the same origin as the CMS, e.g. a page on your own site when the CMS is served from the same domain, has full access to the CMS, including the signed-in user’s access token stored in the browser. Only embed pages you trust.
Link Opening in a New Tab
To add a shortcut to an external site, such as your hosting dashboard or a style guide, set the newTab option to true. The URL is opened in a new browser tab, and the user stays where they are in the CMS.
CMS.registerCustomPage({
id: 'netlify',
label: 'Netlify Dashboard',
icon: 'cloud',
url: 'https://app.netlify.com/sites/example/overview',
newTab: true,
});Migrating from Static CMS
Static CMS provided a similar feature with the CMS.registerAdditionalLink() method. As Static CMS has been archived, Sveltia CMS doesn’t support the method. Use CMS.registerCustomPage() instead:
idandtitlecorrespond toidandlabel, respectively.datacorresponds tocomponentfor a React component, orurlfor a link. AddnewTab: trueto open the link in a new tab, or omit it to embed the page in the CMS.options.iconNamecorresponds toicon, which takes a Material Symbols icon name rather than the name of an icon registered withCMS.registerIcon().