AdminCP Pages
Create powerful admin interfaces for your plugins with protected pages, custom layouts, and integrated navigation.
Pages & Layouts
AdminCP follows the same patterns like from Layouts and Pages but uses the src/app_admin
directory.
Pages
export default function Page() {
return (
<div>
<h1>Settings</h1>
<p>Hello from Blog plugin in AdminCP</p>
</div>
);
}
Layouts
export default function AdminRootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<div className="min-h-screen bg-gray-50">
<header className="border-b bg-white p-4">
<h1 className="text-xl font-semibold">Blog Admin</h1>
</header>
{children}
</div>
);
}
All pages & layouts in the app_admin
directory are automatically protected
and require admin authentication.
Navigation items
To create own navigation items in the admin sidebar you can just create nav
object inside admin
in your plugin config.
Define items in config
As an example let's create a navigation item for blog categories:
import { buildPlugin } from '@vitnode/core/lib/plugin';
import { SettingsIcon } from 'lucide-react';
import { configPlugin } from './config';
export const blogPlugin = () => {
return buildPlugin({
...configPlugin,
admin: {
nav: [
{
id: 'settings',
href: '/admin/blog/settings',
icon: <SettingsIcon />,
},
],
},
});
};
Nested Navigation
To create nested navigation items, you can use the items
property:
import { buildPlugin } from '@vitnode/core/lib/plugin';
import { ListIcon, SettingsIcon } from 'lucide-react';
import { configPlugin } from './config';
export const blogPlugin = () => {
return buildPlugin({
...configPlugin,
admin: {
nav: [
{
id: 'settings',
href: '/admin/blog/settings',
icon: <SettingsIcon />,
items: [
{
id: 'general',
href: '/admin/blog/settings/general',
},
{
id: 'seo',
href: '/admin/blog/settings/seo',
},
],
},
],
},
});
};
Open in new tab
To open a navigation item in a new tab, you can use the isOpenInNewTab
property:
import { buildPlugin } from '@vitnode/core/lib/plugin';
import { SettingsIcon } from 'lucide-react';
import { configPlugin } from './config';
export const blogPlugin = () => {
return buildPlugin({
...configPlugin,
admin: {
nav: [
{
id: 'settings',
href: '/admin/blog/settings',
icon: <SettingsIcon />,
isOpenInNewTab: true,
},
],
},
});
};
Add translation
VitNode automatically uses the id
as translation key for the navigation item.
{
"@vitnode/blog": {
"title": "Blog",
"admin": {
"nav": {
"settings": "Settings"
}
}
}
}