PluginsAdmin Control Panel
Dashboard Widgets
Add a configurable AdminCP dashboard widget from a VitNode plugin with sizing, permissions, and optional settings.
Dashboard widgets are AdminCP plugin extensions. Define the component and register it in the same plugin factory that owns the feature; the host dashboard then discovers it automatically.
Build the widget component
import type { AdminDashboardWidgetProps } from '@vitnode/core/lib/plugin'
export const StatsWidget = ({ settings }: AdminDashboardWidgetProps) => (
<div className="flex flex-col gap-1 p-2">
<span className="text-muted-foreground text-sm">Published notes</span>
<strong className="text-3xl tabular-nums">
{String(settings.total ?? 42)}
</strong>
</div>
)Register it in the existing plugin factory
import { BarChart3Icon } from 'lucide-react'
import { StatsWidget } from './views/admin/widgets/stats-widget'
export const siteNotesPlugin = () =>
buildPlugin({
admin: {
dashboard: {
widgets: [
{
component: StatsWidget,
defaultEnabled: true,
defaultRows: 1,
defaultSpan: 1,
icon: <BarChart3Icon />,
id: 'stats',
},
],
},
},
messages,
pluginId: '@acme/site-notes',
routes,
})The full widget id is namespaced by the plugin, so stats will not collide with
another plugin’s idea of a stats card. A good thing—statistics are dramatic
enough already.
Add a permission or settings UI when needed
Add permission to hide a widget from staff who should not see it. Add
settingsComponent when administrators need to save preferences; both stay in
the plugin alongside the widget.
{
component: StatsWidget,
permission: { module: 'site_notes', permission: 'can_view_stats' },
settingsComponent: StatsSettings,
id: 'stats',
}Widget options
| Option | What it controls |
|---|---|
defaultSpan / defaultRows | Initial grid size from 1 to 3 columns or rows. |
minSpan | Narrowest allowed width. |
defaultEnabled | Whether a new dashboard receives the widget. |
allowMultiple | Whether an admin may place more than one copy. |
permission | Staff permission required to see the widget. |
settingsComponent | Plugin form shown in the widget's panel while the dashboard is being edited. |
How admins arrange them
Your widget does not need any code for this - it is what the dashboard does with every widget. Press Edit layout and the Widgets panel slides in beside the grid.
| To… | Do this |
|---|---|
| Add a widget | Click it in the panel to put it at the end, or drag it onto the grid. While you drag, the grid opens a gap the widget's real size, right where it will land. |
| Change your mind | Drag it back over the panel and let go. Nothing is added, and the card glides back to where it came from. |
| Move a widget | Drag the card from anywhere on it, or Tab to it and use Space and the arrow keys. The spot it came from turns into a dashed slot. |
| Resize a widget | Grab the little bracket in the card's bottom corner and pull. Sideways snaps the width between 1 and 3 columns, down and up snap the height between 1 and 3 rows, and the other widgets glide out of the way. A dashed outline follows your pointer so you can see where you are pulling. From the keyboard, Tab to the corner and use the arrow keys. |
| Edit a widget | Click the card (or Tab to it and press Enter). The panel switches to that widget: a width switch, its own settings form if it has one, and a bin in the header. Save settings stores the settings straight away and leaves the rest of your unsaved arrangement alone. The arrow at the top goes back to the list. |
| Remove a widget | The bin on the card's toolbar, or in its panel. |
| Finish | The panel footer says whether anything changed. Save keeps the arrangement; Cancel throws it away and leaves edit mode. |
New widgets fade in and scroll into view, and screen readers hear where a widget was picked up and dropped in the admin's own language. With reduce motion turned on in the operating system, all of it happens instantly.
The drop gap uses defaultSpan and defaultRows, so pick them to match what the widget looks like the moment it is added.