Aanpak 1: Prefix Rename
Hernoem de route directories met numerieke prefixes zodat de Vite plugin ze in de gewenste volgorde oppakt. Simpelst, geen code wijzigingen nodig behalve directory namen.
+======================================================================+| || ███████╗██╗██████╗ ███████╗██████╗ █████╗ ██████╗ || ██╔════╝██║██╔══██╗██╔════╝██╔══██╗██╔══██╗██╔══██╗ || ███████╗██║██║ ██║█████╗ ██████╔╝███████║██████╔╝ || ╚════██║██║██║ ██║██╔══╝ ██╔══██╗██╔══██║██╔══██╗ || ███████║██║██████╔╝███████╗██████╔╝██║ ██║██║ ██║ || ╚══════╝╚═╝╚═════╝ ╚══════╝╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝ || || S O R T I N G P L A N || || Magic PIM - Medusa 2.11.3 Admin Dashboard || 18 custom routes in de Extensions sidebar || || Status: WACHT OP AKKOORD || Prioriteit: Medium || |+======================================================================+De Magic PIM admin heeft 18 custom routes die allemaal in de “Extensions” sectie van de Medusa sidebar verschijnen. Er is momenteel geen sortering - de volgorde wordt bepaald door de filesystem discovery van de Vite plugin. Dit plan beschrijft 3 aanpakken om de sidebar logisch te ordenen.
| Route | Label | Icon | Categorie |
|---|---|---|---|
/aplt-products | APLT Producten | ShoppingBag | Producten |
/products-by-supplier | Per Leverancier | ShoppingBag | Producten |
/technique-pricing | Print Prijzen | Tag | Producten |
/category-manager | Categorieën | FolderOpen | Producten |
/cms | CMS | DocumentText | Content |
/cms-modules | CMS Modules | Photo | Content |
/page-manager | Page Manager | DocumentText | Content |
/menu-manager | Menu Manager | ListBullet | Content |
/translations | Vertalingen | GlobeEurope | Content |
/connectors | Connectors | ServerStack | Integraties |
/stock-connectors | Stock Connectors | Bolt | Integraties |
/customers | Klanten | Users | Verkoop |
/quotations | Offertes | DocumentText | Verkoop |
/license-manager | License Manager | CreditCard | Systeem |
/license-calculator | Licentie Calculator | CurrencyDollar | Systeem |
/security-groups | Security Groups | ShieldCheck | Systeem |
/tenant-update | Tenant Update | CloudArrowUp | Systeem |
/settings/dev-projects | Dev Projects | CogSixTooth | Settings |
Medusa Admin Sidebar├── Core Routes (vaste volgorde, niet aanpasbaar)│ ├── Orders│ ├── Products│ ├── Inventory│ ├── Customers│ ├── Promotions│ └── Price Lists│├── ─ ─ ─ ─ (dashed divider) ─ ─ ─ ─│└── Extensions (collapsible, onze 18 routes) ├── APLT Producten ← ongesorteerd ├── Per Leverancier ├── CMS ├── ... (filesystem order) └── Tenant UpdateDe nested property kan routes nesten onder core routes (Orders, Products, etc.), maar niet onder andere custom routes. Beschikbare nest-posities:
type NestedRoutePosition = | "/orders" | "/products" | "/inventory" | "/customers" | "/promotions" | "/price-lists";Aanpak 1: Prefix Rename
Hernoem de route directories met numerieke prefixes zodat de Vite plugin ze in de gewenste volgorde oppakt. Simpelst, geen code wijzigingen nodig behalve directory namen.
Hoe het werkt: De Medusa admin Vite plugin scant src/admin/routes/ en genereert menu items op basis van file discovery. Door directories te prefixen met nummers, sturen we de volgorde aan.
Nieuwe directory structuur:
src/admin/routes/├── 01-aplt-products/page.tsx → /01-aplt-products├── 02-products-by-supplier/page.tsx → /02-products-by-supplier├── 03-category-manager/page.tsx → /03-category-manager├── 04-technique-pricing/page.tsx → /04-technique-pricing├── 05-customers/page.tsx → /05-customers├── 06-quotations/page.tsx → /06-quotations├── 07-cms/page.tsx → /07-cms├── 08-cms-modules/page.tsx → /08-cms-modules├── 09-page-manager/page.tsx → /09-page-manager├── 10-menu-manager/page.tsx → /10-menu-manager├── 11-translations/page.tsx → /11-translations├── 12-connectors/page.tsx → /12-connectors├── 13-stock-connectors/page.tsx → /13-stock-connectors├── 14-license-manager/page.tsx → /14-license-manager├── 15-license-calculator/page.tsx → /15-license-calculator├── 16-security-groups/page.tsx → /16-security-groups├── 17-tenant-update/page.tsx → /17-tenant-update└── settings/ └── dev-projects/page.tsx → /settings/dev-projects| Pro | Con |
|---|---|
| Geen code wijzigingen | URL’s veranderen (prefix in path) |
| Werkt direct | Lelijke URL’s (/01-aplt-products) |
| Makkelijk te herschikken | Geen visuele groepering |
| Geen runtime overhead | Filesystem sorting is niet gegarandeerd cross-platform |
Geschiktheid: Snel resultaat, maar niet ideaal voor productie.
Aanpak 2: Nested Routes
Gebruik de nested property van defineRouteConfig om routes onder bestaande Medusa core secties te plaatsen. Dit is de enige officieel ondersteunde manier om sidebar volgorde te beinvloeden.
Hoe het werkt: Routes met nested: "/products" verschijnen als sub-items onder de Products core route in de sidebar, in plaats van in de Extensions sectie.
Configuratie wijzigingen:
export const config = defineRouteConfig({ label: "APLT Producten", icon: ShoppingBag, nested: "/products", // ← nest onder Products})
// products-by-supplier/page.tsxexport const config = defineRouteConfig({ label: "Per Leverancier", icon: ShoppingBag, nested: "/products", // ← nest onder Products})
// technique-pricing/page.tsxexport const config = defineRouteConfig({ label: "Print Prijzen", icon: Tag, nested: "/products", // ← nest onder Products})
// category-manager/page.tsxexport const config = defineRouteConfig({ label: "Categorieën", icon: FolderOpen, nested: "/products", // ← nest onder Products})
// customers/page.tsxexport const config = defineRouteConfig({ label: "Klanten", icon: Users, nested: "/customers", // ← nest onder Customers})
// quotations/page.tsxexport const config = defineRouteConfig({ label: "Offertes", icon: DocumentText, nested: "/customers", // ← nest onder Customers (B2B context)})Resultaat sidebar:
Medusa Admin Sidebar├── Orders├── Products│ ├── APLT Producten ← genest│ ├── Per Leverancier ← genest│ ├── Print Prijzen ← genest│ └── Categorieën ← genest├── Inventory├── Customers│ ├── Klanten ← genest│ └── Offertes ← genest├── Promotions├── Price Lists│├── ─ ─ ─ (Extensions) ─ ─ ─│└── Extensions (overige 10 routes) ├── CMS ├── CMS Modules ├── Page Manager ├── Menu Manager ├── Vertalingen ├── Connectors ├── Stock Connectors ├── License Manager ├── Licentie Calculator ├── Security Groups └── Tenant Update| Pro | Con |
|---|---|
| Officieel ondersteund door Medusa | Slechts 6 nest-posities beschikbaar |
| Geen URL wijzigingen | Content/Systeem routes kunnen niet genest worden |
| Logische groepering | Extensions sectie blijft ongesorteerd |
| Geen custom code nodig | Beperkt tot core route categorieën |
Geschiktheid: Goed voor product- en klant-gerelateerde routes. Lost het probleem niet volledig op voor CMS/Systeem routes.
Aanpak 3: Custom Sidebar
Overschrijf de Medusa admin sidebar met een custom React component dat volledige controle geeft over groepering, volgorde en visuele presentatie. Dit is de meest complete oplossing.
Hoe het werkt: Maak een custom sidebar component die de standaard Extensions sectie vervangt met gegroepeerde, gesorteerde navigatie. Dit vereist het patchen van de Medusa dashboard bundle of het injecteren via een admin widget.
Gewenste sidebar layout:
Medusa Admin Sidebar├── [Searchbar]│├── CORE│ ├── Orders│ ├── Products│ ├── Inventory│ ├── Customers (Medusa)│ ├── Promotions│ └── Price Lists│├── PRODUCTEN│ ├── APLT Producten│ ├── Per Leverancier│ ├── Categorieën│ └── Print Prijzen│├── VERKOOP│ ├── Klanten│ └── Offertes│├── CONTENT│ ├── CMS│ ├── CMS Modules│ ├── Page Manager│ ├── Menu Manager│ └── Vertalingen│├── INTEGRATIES│ ├── Connectors│ └── Stock Connectors│├── SYSTEEM│ ├── License Manager│ ├── Licentie Calculator│ ├── Security Groups│ └── Tenant Update│└── SETTINGS └── Dev ProjectsImplementatie:
Stap 1 - Maak een sidebar configuratie bestand:
export type SidebarGroup = { label: string items: { path: string; label: string; icon: string }[]}
export const sidebarGroups: SidebarGroup[] = [ { label: "Producten", items: [ { path: "/aplt-products", label: "APLT Producten", icon: "ShoppingBag" }, { path: "/products-by-supplier", label: "Per Leverancier", icon: "ShoppingBag" }, { path: "/category-manager", label: "Categorieën", icon: "FolderOpen" }, { path: "/technique-pricing", label: "Print Prijzen", icon: "Tag" }, ], }, { label: "Verkoop", items: [ { path: "/customers", label: "Klanten", icon: "Users" }, { path: "/quotations", label: "Offertes", icon: "DocumentText" }, ], }, { label: "Content", items: [ { path: "/cms", label: "CMS", icon: "DocumentText" }, { path: "/cms-modules", label: "CMS Modules", icon: "Photo" }, { path: "/page-manager", label: "Page Manager", icon: "DocumentText" }, { path: "/menu-manager", label: "Menu Manager", icon: "ListBullet" }, { path: "/translations", label: "Vertalingen", icon: "GlobeEurope" }, ], }, { label: "Integraties", items: [ { path: "/connectors", label: "Connectors", icon: "ServerStack" }, { path: "/stock-connectors", label: "Stock Connectors", icon: "Bolt" }, ], }, { label: "Systeem", items: [ { path: "/license-manager", label: "License Manager", icon: "CreditCard" }, { path: "/license-calculator", label: "Licentie Calculator", icon: "CurrencyDollar" }, { path: "/security-groups", label: "Security Groups", icon: "ShieldCheck" }, { path: "/tenant-update", label: "Tenant Update", icon: "CloudArrowUp" }, ], },]Stap 2 - Injecteer via CSS + JS in de admin build:
// Widget that re-orders the Extensions section via DOM manipulation// after Medusa renders the default sidebar
import { defineWidgetConfig } from "@medusajs/admin-sdk"import { useEffect } from "react"import { sidebarGroups } from "../config/sidebar-order"
const SidebarSortWidget = () => { useEffect(() => { // Re-order extension nav items based on sidebarGroups config const reorder = () => { const extensionNav = document.querySelector( '[class*="flex flex-col gap-y-0.5 py-1 pb-4"]' ) if (!extensionNav) return
const items = Array.from(extensionNav.children) as HTMLElement[] const orderedPaths = sidebarGroups.flatMap(g => g.items.map(i => i.path))
// Sort items based on config order const sorted = orderedPaths .map(path => items.find(el => el.querySelector(`a[href="${path}"]`))) .filter(Boolean) as HTMLElement[]
// Re-append in order (moves existing DOM nodes) sorted.forEach(item => extensionNav.appendChild(item)) }
// Run after Medusa renders const timer = setTimeout(reorder, 500) return () => clearTimeout(timer) }, [])
return null // invisible widget}
export const config = defineWidgetConfig({ zone: "order.list.before", // any zone to ensure it loads})
export default SidebarSortWidget| Pro | Con |
|---|---|
| Volledige controle over volgorde | Vereist custom code |
| Visuele groepering met headers | DOM manipulation is fragiel |
| Geen URL wijzigingen | Kan breken bij Medusa updates |
| Schaalbaar (config-driven) | Complexer dan aanpak 1 en 2 |
| Mooiste eindresultaat | Moet getest worden na elke Medusa upgrade |
Geschiktheid: Beste resultaat, maar meeste werk. Ideaal als langetermijn oplossing.
Fase 1: Nested Routes (30 minuten)
Voeg nested toe aan 6 routes die logisch onder core secties vallen:
aplt-products → nested: "/products"products-by-supplier → nested: "/products"technique-pricing → nested: "/products"category-manager → nested: "/products"customers → nested: "/customers"quotations → nested: "/customers"Dit verplaatst 6 van de 18 routes uit de Extensions sectie naar logische plekken.
Fase 2: Evalueer (1 week gebruiken)
Gebruik de admin een week met de nested routes. Bepaal of de overige 12 routes in Extensions voldoende zijn, of dat groepering nodig is.
Fase 3: Custom Sidebar (optioneel, 1-2 dagen)
Als groepering gewenst is, implementeer de custom sidebar config met gegroepeerde navigatie voor de overige CMS, Integraties en Systeem routes.
Wijzigingen aan defineRouteConfig vereisen:
/mnt/data/magic_pim/backend/src/admin/routes/*/page.tsxnpx medusa build uitvoerensudo -u adminwayne pm2 restart magic-pim-backend)