Extend the Medusa v2 admin dashboard — widgets injected at zones, custom UI routes, Medusa UI components, and Admin API integration. Use when customizing the admin interface.
Scanned 9/7/2026
Install to Claude Code
npx -y skills add OrcaQubits/agentic-commerce-skills-plugins --skill medusa-admin --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Medusa Admin?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/orcaqubits-medusa-admin-agentic-commerce-skills-plugin)More formats (shields.io, HTML) on the badges page.
---
name: medusa-admin
description: Extend the Medusa v2 admin dashboard — widgets injected at zones, custom UI routes, Medusa UI components, and Admin API integration. Use when customizing the admin interface.
allowed-tools: Read, Write, Edit, Bash, Grep, Glob, WebSearch, WebFetch
---
# Medusa v2 Admin Dashboard Extensions
## Before writing code
**Fetch live docs**:
1. Fetch `https://docs.medusajs.com/learn/fundamentals/admin/widgets` for widget development
2. Web-search `site:docs.medusajs.com admin UI routes` for custom admin pages
3. Web-search `site:docs.medusajs.com admin widget injection zones` for available zones
4. Web-search `site:docs.medusajs.com medusa UI components` for component library
5. Web-search `site:docs.medusajs.com admin API client` for making API calls from admin
## Admin Extension Concept
Medusa v2 admin is a React-based SPA that supports two extension types:
- **Widgets** -- injected into predefined zones on existing admin pages
- **UI Routes** -- entirely new pages accessible via the admin sidebar or navigation
Extensions live in `src/admin/` and are automatically discovered and bundled.
## Admin Extension Directory Structure
| Directory | Purpose |
|-----------|---------|
| `src/admin/widgets/` | Widget components (e.g., `product-custom-widget.tsx`) |
| `src/admin/routes/custom-page/page.tsx` | Custom admin page |
| `src/admin/routes/custom-page/[id]/page.tsx` | Dynamic route page |
| `src/admin/lib/` | Shared API utilities |
## Widgets
### Widget Injection Zones
| Zone | Location | Use Case |
|------|----------|----------|
| `product.details.before` | Product detail, top | Custom product fields |
| `product.details.after` | Product detail, bottom | Related data display |
| `product.details.side.before` | Product detail sidebar, top | Quick actions |
| `product.details.side.after` | Product detail sidebar, bottom | Metadata display |
| `order.details.before` | Order detail, top | Custom order info |
| `order.details.after` | Order detail, bottom | Fulfillment tracking |
| `order.details.side.before` | Order sidebar, top | Order tags |
| `order.details.side.after` | Order sidebar, bottom | Order notes |
| `customer.details.before` | Customer detail, top | Loyalty info |
| `customer.details.after` | Customer detail, bottom | Purchase history |
> **Fetch live docs** for the complete zone list -- zones are added with each Medusa release.
### Widget Definition Skeleton
```typescript
// src/admin/widgets/product-custom-widget.tsx
// Fetch live docs for defineWidgetConfig and zone types
import { defineWidgetConfig } from "@medusajs/admin-sdk"
import { Container, Heading } from "@medusajs/ui"
const ProductCustomWidget = ({ data }) => (
<Container><Heading level="h2">Custom</Heading></Container>
)
```
```typescript
export const config = defineWidgetConfig({ zone: "product.details.after" })
export default ProductCustomWidget
```
### Widget Props
| Prop | Type | Description |
|------|------|-------------|
| `data` | Entity object | The entity displayed on the page (product, order, etc.) |
The `data` prop shape depends on the zone -- a `product.details.*` zone receives the product object.
## Custom UI Routes
### Route File Convention
| File Path | Admin URL |
|-----------|-----------|
| `src/admin/routes/custom-page/page.tsx` | `/app/custom-page` |
| `src/admin/routes/custom-page/[id]/page.tsx` | `/app/custom-page/:id` |
| `src/admin/routes/settings/my-setting/page.tsx` | `/app/settings/my-setting` |
### Route Page Skeleton
```typescript
// src/admin/routes/custom-page/page.tsx
// Fetch live docs for defineRouteConfig
import { defineRouteConfig } from "@medusajs/admin-sdk"
import { Container, Heading } from "@medusajs/ui"
const CustomPage = () => (
<Container><Heading level="h1">Custom Page</Heading></Container>
)
```
```typescript
export const config = defineRouteConfig({ label: "Custom Page" })
export default CustomPage
// Fetch live docs for icon options in defineRouteConfig
```
### Adding Sidebar Navigation
The `defineRouteConfig` with a `label` property automatically adds the page to the admin sidebar. Pages under `routes/settings/` appear in the Settings section.
## Medusa UI Component Library
| Category | Key Components |
|----------|---------------|
| Layout | `Container`, `Drawer`, `FocusModal`, `Prompt` |
| Typography | `Heading`, `Text`, `Label`, `Code` |
| Forms | `Input`, `Select`, `Checkbox`, `RadioGroup`, `Switch`, `Textarea`, `DatePicker` |
| Data | `Table`, `Badge`, `StatusBadge`, `Avatar`, `Copy` |
| Actions | `Button`, `IconButton`, `DropdownMenu`, `CommandBar` |
| Feedback | `Toast`, `Alert`, `ProgressBar`, `Spinner` |
| Navigation | `Tabs`, `Breadcrumbs` |
> **Fetch live docs**: Web-search `site:docs.medusajs.com @medusajs/ui components` for the full component catalog and prop APIs.
## Making Admin API Calls
### Using the Medusa JS SDK
```typescript
// Fetch live docs for admin SDK client setup
// Use the SDK or fetch wrapper provided by Medusa admin
// Fetch live docs for createAdminClient or useAdminXxx hooks
const { data } = await sdk.admin.product.list()
```
### Using fetch with Admin Auth
Admin extensions run within the authenticated admin session. Use the built-in `fetch` wrapper or the JS SDK which automatically includes session credentials.
## Admin API Scopes
| Scope | Endpoints | Requires |
|-------|-----------|----------|
| Store API (`/store/*`) | Storefront operations | Optional customer auth |
| Admin API (`/admin/*`) | Back-office operations | Admin user session |
| Custom (`/admin/custom/*`) | Custom admin endpoints | Admin auth middleware |
Custom admin pages typically call `/admin/*` endpoints which require the admin session token.
## Limitations
| Limitation | Workaround |
|-----------|-----------|
| Cannot modify core admin pages | Use widgets injected at zones |
| Cannot override core admin routes | Create new routes with custom functionality |
| Limited styling control | Use `@medusajs/ui` components for consistency |
| No server-side rendering | Admin is a client-side SPA |
| Bundle size | Keep widget dependencies minimal |
## Best Practices
- Use `@medusajs/ui` components for visual consistency with the core admin
- Keep widgets focused on a single concern -- use multiple widgets for multiple features
- Use custom UI routes for complex multi-step interfaces
- Call the Admin API through the JS SDK or built-in fetch wrapper -- do not hardcode URLs
- Type your widget `data` prop for type safety
- Place shared utilities in `src/admin/lib/` for reuse across widgets and routes
## Testing Admin Extensions
| Approach | Description |
|----------|-------------|
| Storybook | Render components in isolation with `@medusajs/ui` |
| Browser testing | Run `npx medusa develop` and manually verify |
| Unit tests | Test logic functions separately from React rendering |
Fetch the Medusa admin extension documentation for exact injection zone names, component props, and route configuration options before implementing.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!