page.tsx under a panel’s src/routes/ folder and the SDK registers it at build
time, the same way Next.js and Remix
map folders to routes.
This guide walks through creating a page, then documents the routing conventions,
the sidebar config, and the defineNavigationConfig and createFormHelper
helpers.
Create a page
1
Add a page file
Create The default export is the only required part. Only files named
page.tsx in a new folder under src/routes/. The folder path becomes
the URL, so this file mounts at /erp-sync.apps/vendor/src/routes/erp-sync/page.tsx
page register
as routes, so you can co-locate a loader.ts or components in the same folder.2
Add it to the sidebar
A page has no sidebar entry until it exports a
config with a label. The
config is a plain object.apps/vendor/src/routes/erp-sync/page.tsx
3
Run the panel
Start the panel and open the route. The page renders and its sidebar entry
appears.The vendor panel runs on
Terminal
http://localhost:7001 and the admin panel on
http://localhost:7000.Route paths
Folder and file names map to path segments. Wrap a segment in brackets or parentheses to make it dynamic or optional.
Read a dynamic segment with React Router’s
useParams(). A file at
src/routes/orders/[id]/page.tsx mounts at /orders/:id.
Where the page mounts
The route path and the page’sconfig.public flag decide which layout wraps the
page.
Main and settings routes render inside the authenticated shell. Public routes
render on their own, so use them for pages a signed-out user must reach.
Sidebar config
Theconfig object controls the page’s sidebar entry.
A page can exist without a sidebar entry. Omit
label when the route is reached
from a link or a widget rather than the sidebar.Load data for a page
Export aloader to fetch data before the component renders, and a handle to
attach route metadata such as a breadcrumb. Both are React Router route options,
picked up as named exports.
apps/vendor/src/routes/erp-sync/page.tsx
useLoaderData() inside the component.
Reshape built-in navigation
UsedefineNavigationConfig to reorder, hide, relabel, or re-parent built-in
sidebar items. It lives in a single host-owned file, src/_navigation.ts. Blocks
cannot contribute navigation overrides.
apps/vendor/src/_navigation.ts
NavItemOverride.
Navigation overrides reshape existing items only. To add a new item, register a
page with a
config.label as shown above.
Type a page’s forms
createFormHelper<T>() returns Medusa’s Zod surface for describing field
validation and value types. Import it from @mercurjs/dashboard-shared.
validation types the value. See Custom Fields
for where form.define fields are attached.
Next steps
Widgets
Render a component in a slot on an existing page.
Custom Fields
Add fields, section rows, and list columns to a built-in model.