AdminCP Pages
Add plugin-owned AdminCP pages, navigation, permissions, and dashboard extensions to the VitNode admin panel.
AdminCP is a plugin surface. Give the plugin an area: 'admin' route and a
browser-safe navigation declaration. The host supplies the panel shell; your
plugin supplies the useful bit.
Claim an AdminCP route
import { definePluginRoutes, lazy, page } from '@vitnode/core/routing'
export const routes = definePluginRoutes([
page('/admin/site-notes/settings', {
area: 'admin',
component: lazy(() => import('./pages/admin-settings-page')),
}),
])Render the plugin page
const AdminSettingsPage = () => (
<div className="flex flex-col gap-2 p-4">
<h2 className="text-2xl font-semibold">Site notes settings</h2>
<p className="text-muted-foreground">Manage the notes plugin.</p>
</div>
)
export default AdminSettingsPageAdd a sidebar entry
Export adminNav from the plugin. Its small browser-safe shape is what the
generated AdminCP registry imports—do not edit admin-nav.gen.ts yourself.
import type { AdminNavPluginSource } from '@vitnode/core/lib/plugin'
import { SettingsIcon } from 'lucide-react'
export const adminNav = {
pluginId: '@acme/site-notes',
admin: {
nav: [
{
href: '/admin/site-notes/settings',
icon: <SettingsIcon />,
id: 'settings',
permission: { module: 'site_notes', permission: 'can_manage_settings' },
},
],
},
} satisfies AdminNavPluginSourceThe generator’s ./* package export already exposes admin/nav; no manual
package.json export is required, and nothing changes in config.tsx. The
generated admin-nav.gen.ts imports admin/nav directly, and keeping the
factory to plain data is what keeps the sidebar registration out of every
public page's bundle.
Verify the screen
bun devVisit http://localhost:3000/admin/site-notes/settings as a staff account with
the declared permission.