Core

Dashboard

The admin home page, its widgets, and how to add your own.

The admin home is /admin/home. It shows a header and a grid of widgets.

The header has the date, the title "Dashboard", and a create button. With one content type, the button reads "New <label>". With several types, it is a Create menu.

Core widgets

WidgetOrderColumnsShows
content-overview03One tile for each content type
content-activity102Items created each week, for the last 12 weeks
quick-actions201Create commands and a few admin destinations

content-overview and content-activity are off while no content type is registered.

Content tiles

Each tile shows the plural label, an icon, and the total. When activity data exists, it adds "+N this week". For a type with a status workflow, it adds a meter of the published share and the text "N published · M drafts". The text says the same numbers, so the share never depends on color alone.

A tile links to the list of the type.

Activity chart

The chart shows an area for one content type and lines for several. The series colors come from the admin theme.

A hidden table has the same numbers. The chart shows a skeleton while it loads, an error alert with Try again, "Activity is not available" when no adapter can count by creation date, and an empty state when nothing was created.

The data comes from this route:

GET /api/_pluto/content-activity/<type>?weeks=12

weeks is from 1 to 52. The answer is { supported, interval: 'week', points: [{ start, count }] }, oldest first. Weeks start on Monday, in UTC.

The route calls the optional countCreated(ctx, { from, to }) of the adapter once for each week. It returns supported: false when the adapter has no such method, or when the method returns null.

Quick actions

The widget shows the same Create and Go to commands as the command palette, without Home.

Add a widget

app/plugins/pluto-registrations.ts
const RecentPostsWidget = defineAsyncComponent(() => import('../components/RecentPostsWidget.vue'))

export default defineNuxtPlugin(() => {
  definePlutoExtension({
    id: 'supabase-blog',
    dashboardWidgets: [
      { id: 'recent-posts', component: RecentPostsWidget, colSpan: 2 }
    ]
  })
})

A widget with the default order (100) goes below the core widgets. The grid has 3 columns on the lg breakpoint.

Each widget has its own <Suspense>. The grid paints at once. A card skeleton shows until the widget code loads. The skeleton height depends on colSpan.

Translation

All dashboard text is translated. Numbers and dates use n() and d(), so they follow the admin language.