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’ssrc. The create-mercur-app scaffold already ships this file.
apps/vendor/src/extension-targets.d.ts
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
- The top-level order reflects your
rankvalues, withordersfirst. price-listsno longer appears in the sidebar.campaignsrenders as a child under Orders.- Set
id: "not-an-item".bun run lint(tsc) fails againstNavItemRegistry. - Delete
_navigation.ts. The default sidebar returns.
FAQ
What ids can I target?
What ids can I target?
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.Does this work in the admin panel too?
Does this work in the admin panel too?
Yes. Drop
src/_navigation.ts in the admin app and reference @mercurjs/admin/extension-targets. Each panel ships its own nav id set.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.