<Slot name="…"> call sites in the dashboard source (linked under Reference below); each entry here records the host page, the slot name, and the context your component receives.
If you need a new injection point in a built-in page, open a PR adding <Slot name="..." context={...} /> and a documentation entry here — that’s the contract for new slots.
At a glance
Ambient context
Ambient context (permissions, store, user merged into every slot’s props) is planned but not wired up yet — today slot components receive only the slot-specific context listed below. Until it lands, read those values with the hooks instead:
if predicate: it receives the slot context, but not permissions — gate inside the component for now.
Page header slots
Rendered by<PageHeader> (@spree/dashboard-core/components/page-header.tsx) at the top of every detail and list page that uses the shared chrome.
page.actions
page.actions_dropdown
Page tabs slot
page.tabs (default)
Rendered by <PageTabs> at the right edge of any tabbed sub-nav.
Some pages override
slotName to scope tabs to a single resource (e.g., slotName="order.tabs"). The catalog will grow these as we wire them up; today only the default page.tabs name is in production use.
Detail-page slots
Every resource detail page renders a slot at the end of its sidebar column, and some also at the end of the main column. The slot name starts with the resource name, and the context key matches it. Host form. On pages marked host form: yes, the slot renders inside the page’s own<form> and exposes it — widgets can bind inputs via useHostForm() that hydrate, dirty-track, and save with the page’s Save button. The form key is what you register extension fields under in formFields. On every other page, widgets own their persistence; use useOptionalHostForm() to write a widget that adapts to both.
On host-form pages your widget renders inside the page’s
<form> element, so a <Button> in it submits the page unless you give it type="button".Products
product.form_sidebar
category.form_sidebar
collection.form_sidebar
catalog.form_sidebar
price_list.form_sidebar
Orders and customers
order.form_sidebar
customer.form_sidebar
company.form_main
company.form_sidebar
Company membership slots
The company’s member list and its “Add member” sheet carry three smaller slots, built for an extension that gives members roles.Promotions
promotion.form_sidebar
Inventory
purchase_order.form_sidebar
stock_transfer.form_sidebar
Sellers (marketplace)
These slots are on the store owner’s seller management pages in the admin dashboard. For the seller’s own view, see the seller panel slots below.seller.form_main
seller.form_sidebar
seller_payout.form_main
seller_payout.form_sidebar
Settings
store.form_main
webhook_endpoint.form_sidebar
Seller panel slots
Rendered by the marketplace seller panel (@spree/seller-dashboard) rather than the admin dashboard, and registered the same way, in the seller panel’s own plugins. Their names start with seller. followed by the page — seller.form_main and seller.form_sidebar above belong to the admin dashboard instead.
The product page is a host form with the form key seller.product: fields a widget binds with useHostForm() save with the product. The Seller API accepts only the attributes your extension declares in additional_seller_permitted_attributes — see Writable by sellers. The other seller panel pages have no page-wide form, so widgets there save via their own Seller API calls.
Replaceable slots
These slots render built-in content when nothing is registered. Registering a component replaces that content rather than adding to it.no_store_access
Import the name as
NO_STORE_ACCESS_SLOT from @spree/dashboard-core rather than typing it.
getting-started.task.<name>
<name> is the task’s name as the API returns it.
Editor slots (dynamic)
Promotions, price lists, and payment methods each pick their editor by type. The slot names are computed from the type’sapi_type shorthand, so registering against the right name is what hooks your editor in. The promotion and price list editor slots replace the built-in editor, which is generated from the type’s preference schema.
promotion.rule_form.<type>
promotion.action_form.<type>
price_list.rule_form.<type>
Payment method editor slots
Used by<PaymentMethodForm> to let payment-provider plugins replace pieces of the editor sheet. The slot names are computed per provider type (stripe, bogus, …), so registering against the right name is what hooks your editor in.
payment_method.guide.<providerType>
payment_method.form.<providerType>
payment_method.actions.<providerType>
PaymentMethodEditorContext
Adding a new slot
If a built-in page should expose a new injection point:- Pick a name (
<resource>.<area>, e.g.,order.timeline;seller.<page>.<area>in the seller panel) - Add
<Slot name="..." context={{ resource: order, /* ... */ }} />at the call site - If the slot sits inside the page’s form, make it a host form: wrap the form in
<FormProvider>, hydrate withextensionFormValues('<resource>', record), and mergeextensionSubmitValues('<resource>', form)into the save payload — the collection page is the reference - Document the slot here — host, intent, context shape, and form key
- Open the PR
Reference
<Slot>sourceslot-registry—registerSlot,removeSlot,updateSlot,useSlotEntries- Slots customization page — how to register against a slot

