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/routes/admin directory. Like everywhere in VitNode, render text with translations — see Messages.
Pages
import { getTranslations } from 'next-intl/server';
export default async function Page() {
const t = await getTranslations('@vitnode/blog.admin.settings');
return (
<div>
<h1>{t('title')}</h1>
<p>{t('desc')}</p>
</div>
);
}Layouts
import { getTranslations } from 'next-intl/server';
export default async function AdminRootLayout({
children,
}: {
children: React.ReactNode;
}) {
const t = await getTranslations('@vitnode/blog.admin.settings');
return (
<div className="min-h-screen bg-gray-50">
<header className="border-b bg-white p-4">
<h1 className="text-xl font-semibold">{t('title')}</h1>
</header>
{children}
</div>
);
}All pages & layouts in the src/routes/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"
}
}
}
}