Skip to main content
Reshape the built-in sidebar without replacing it. You author one host-owned file, src/_navigation.ts, and it reorders, hides, relabels, and re-parents the built-in items. The sidebar ships a fixed set of items such as Orders, Products, and Customers. _navigation.ts is the single source of truth for their shape. It overrides existing items only, so a new item still comes from a page you add.
When to use this vs. a config export. New pages you add via drop-in routes place their own sidebar item through defineRouteConfig({ label, rank, nested }). _navigation.ts is for the items you didn’t create, the built-in ones. The two layer cleanly: custom routes place themselves, and _navigation.ts reshapes the built-ins.

What you’ll build

A vendor sidebar with Orders pinned to the top, Price Lists hidden, and Campaigns moved under Orders.

Register the typed targets

Nav item ids are typed and generated per panel. Register them once with a single ambient reference in your app’s src. The create-mercur-app scaffold already ships this file.
apps/vendor/src/extension-targets.d.ts
With it present, id and nested autocomplete and an unknown id fails tsc.

Author the navigation file

1

Create src/_navigation.ts

The file is host-owned and underscore-prefixed. Default-export a defineNavigationConfig with an items array of overrides.
apps/vendor/src/_navigation.ts
2

Know the override fields

Each entry targets one built-in item by its stable id.Both id and nested are checked against the panel’s generated NavItemRegistry and NavParentRegistry.
3

Reload the panel

Open the vendor portal. Orders sits at the top, Price Lists is gone from the menu, and Campaigns now appears under Orders.
The route for a hidden item stays reachable directly by URL unless you also remove it.

Common recipes

Verify

  1. The top-level order reflects your rank values, with orders first.
  2. price-lists no longer appears in the sidebar.
  3. campaigns renders as a child under Orders.
  4. Set id: "not-an-item". bun run lint (tsc) fails against NavItemRegistry.
  5. Delete _navigation.ts. The default sidebar returns.

FAQ

No. Navigation is deliberately host-only. Blocks can ship pages, widgets, and custom fields, but the sidebar order stays a single source of truth in your app’s _navigation.ts.
Any built-in item, top-level or nested, by its own id, such as orders, products, categories, collections, campaigns, or customer-groups. Let your editor autocomplete id: against NavItemId. The full set is generated into your panel’s extension-targets.d.ts.
Yes. Drop src/_navigation.ts in the admin app and reference @mercurjs/admin/extension-targets. Each panel ships its own nav id set.
That’s a drop-in route with a config export. _navigation.ts only reshapes built-in items, it doesn’t create routes.

Next steps

Add a custom panel page

Add a new screen with its own sidebar item.

Add a widget

Inject a component into a built-in page.