Skip to main content
The dashboard is structured as three packages. This page lists the symbols we commit to keeping — treat anything not listed as internal, liable to move or be renamed without a deprecation cycle, even where the barrel happens to export it today. Never reach past a package entry point into @spree/dashboard-core/src/....

@spree/dashboard-core

Default-import surface for plugins and customizations.

Plugin facade

Single declarative entry-point for every registry. See Customization Quickstart for the full shape.

Registries

Each registry exposes add/remove/update-style mutators. See the per-feature pages for examples — form fields and custom field components are covered in the custom form field recipe.

Components

Hooks

Helpers

SDK client

The shared @spree/admin-sdk instance configured for the host’s API URL. Use this everywhere instead of constructing your own.

Providers

Mount these at the root of your app shell. The shipped app shell does this for you — re-export only if you’re composing a custom shell (vendor panel, etc.).

Vite plugin

Vite plugin that resolves third-party dashboard plugins and injects Tailwind @source directives for their CSS. See Distributing for the host wiring.

@spree/dashboard-ui

Design system primitives. Headless — accept data via props, never reach for providers or hooks.

shadcn-style primitives

Toast notifications come from sonner directly — import { toast } from 'sonner' — while <Toaster> (the mount point, already rendered by the app shell) is the only part re-exported here.

Composed components

Higher-level pieces that bundle multiple primitives but still take data via props:
Empty* composes via children (icon in <EmptyMedia>, actions in <EmptyContent>) rather than taking title/description props.

Utilities

@spree/dashboard

The app shell, and the single import a host application needs. It re-exports everything from @spree/dashboard-core and @spree/dashboard-ui, so code in your own dashboard app never has to work out which package an export lives in:
Plugins don’t import from here — a plugin extends the dashboard through @spree/dashboard-core and never renders the shell, so importing the shell would pull the whole app into a package meant to plug into it. The host (the dashboard-starter project, or a create-spree-app project) is also what mounts the admin:
  • Dashboard — the app shell component (provider stack + router). Render it with a router: <Dashboard router={router} />.
  • createDashboardRouter(routeTree) — builds the router from the host’s generated routeTree.gen.ts (the shell’s routes composed with every installed plugin’s file routes). The starter’s main.tsx wires these together; you rarely write this by hand.
Two subpath entries complete the surface:
A few names exist in both re-exported packages — the design system ships a presentational component and the framework wraps it with data (ResourceCombobox, StatusCard, Slot, DateRange, ResourceMultiAutocomplete). The facade gives you the framework’s version, which is the one an application wants. Reach past it when you want the presentational half:
Importing from @spree/dashboard pins your code to the deployable app’s version, which is what a host app wants and what a distributed plugin must avoid.

What about @spree/admin-sdk?

The Admin API client is a separate package and a public dependency. Import types and SpreeError from it directly:
The adminClient instance, by contrast, comes from @spree/dashboard-core so the host owns the configured singleton.

Stability

Anything on this page is covered by semver from @spree/dashboard-core 1.0.0 onward. Pre-1.0 we may rename, but we’ll call breaking moves out in the changelog. Anything not listed here is internal. If you find yourself wanting it, open a discussion — it’s a sign we should promote it to the public surface.

Reference