docs: updates to admin customization docs (#7493)

* updated admin docs

* re-add navigation and parameters sections

* update injection zones

* update cli scripts docs

* added list of injection zones

* add details about widget props

* restructure admin injection zones
This commit is contained in:
Shahed Nasser
2024-05-29 13:50:19 +03:00
committed by GitHub
parent 72b57e2ae4
commit 130de74d6d
15 changed files with 1753 additions and 3023 deletions

File diff suppressed because one or more lines are too long

View File

@@ -4,19 +4,12 @@ export const metadata = {
# {metadata.title}
<Note type="soon">
Admin customizations are coming soon.
</Note>
In the next chapters, you'll learn more about possible admin customizations.
You can customize the admin dashboard by:
- Adding new sections to existing pages using Widgets.
- Adding new pages using UI Routes.
- Adding new pages to the Settings section of the admin dashboard using Setting Pages.
---

View File

@@ -1,152 +0,0 @@
export const metadata = {
title: `${pageNumber} Admin Setting Pages`,
}
# {metadata.title}
<Note type="soon">
Admin customizations are coming soon.
</Note>
In this chapter, youll learn how to create a setting page in the admin dashboard.
## What is a Setting Page?
A setting page is a React component that adds a new page to the settings panel of the admin dashboard.
For example, you may create a setting page to manage configurations related to your custom functionalities.
---
## How to Create a Setting Page?
A setting page is created in a file named `page.tsx` under the `src/admin/settings` directory. The files default export must be the React component, and it must also export a configuration object.
For example, you can create the file `src/admin/settings/custom/page.tsx` with the following content:
```tsx title="src/admin/settings/custom/page.tsx"
import type { SettingConfig } from "@medusajs/admin"
import { ChatBubbleLeftRight } from "@medusajs/icons"
const CustomSettingPage = () => {
return (
<div>
<h1>Custom Setting Page</h1>
</div>
)
}
export const config: SettingConfig = {
card: {
label: "Custom",
description: "Manage your custom settings",
// optional
icon: ChatBubbleLeftRight,
},
}
export default CustomSettingPage
```
The new setting pages path is the files path relative to `src/admin/settings` and prefixed with `/a/settings`. So, the above UI route is a new page added at the path `localhost:7001/a/settings/custom`.
The setting page is shown on the Settings panel as a card. In the exported configuration object, you configure the cards label, description, and optionally icon. In this example, you use an icon from [Medusas UI Icons package](https://docs.medusajs.com/ui/icons/overview).
### Test the Setting Page
To test the setting page, start the Medusa application:
```bash npm2yarn
npm run dev
```
Then, open the Settings page of the admin dashboard. Youll find a new card that links to your setting page.
---
## Using UI Components
Similar to other admin customizations, its highly recommended that you use the [Medusa UI package](https://docs.medusajs.com/ui) to match your pages design with the rest of the Medusa Admin.
For example, you can rewrite the above UI route to the following:
```tsx title="src/admin/settings/custom/page.tsx"
import type { SettingConfig } from "@medusajs/admin"
import { ChatBubbleLeftRight } from "@medusajs/icons"
import { Container, Heading } from "@medusajs/ui"
const CustomSettingPage = () => {
return (
<Container>
<Heading level="h1">Custom Setting Page</Heading>
</Container>
)
}
export const config: SettingConfig = {
card: {
label: "Custom",
description: "Manage your custom settings",
icon: ChatBubbleLeftRight,
},
}
export default CustomSettingPage
```
---
## Setting Page Props
A setting page receives a `notify` prop, which is an object having the following properties:
- `success`: a function that shows a success toast message.
- `error`: a function that shows an error toast message.
- `warn`: a function that shows a warning toast message.
- `info`: a function that shows an info toast message.
Each of these functions accepts two parameters: the messages title and the messages content.
For example:
```tsx title="src/admin/settings/custom/page.tsx" highlights={[["11", "success", "Show a success toast message on the click of a button."]]}
import type { RouteProps, SettingConfig } from "@medusajs/admin"
import { ChatBubbleLeftRight } from "@medusajs/icons"
import { Container, Heading, Button } from "@medusajs/ui"
const CustomSettingPage = ({ notify }: RouteProps) => {
return (
<Container>
<Heading level="h1">Custom Setting Page</Heading>
<Button
onClick={() =>
notify.success("Success!", "You clicked the button!")
}
className="mt-3"
>
Click me
</Button>
</Container>
)
}
export const config: SettingConfig = {
card: {
label: "Custom",
description: "Manage your custom settings",
icon: ChatBubbleLeftRight,
},
}
export default CustomSettingPage
```
If you click the button on your setting page, a toast message will show with the title and message you specified.
<Note title="Tip">
Admin UI Routes support [Tailwind CSS](https://tailwindcss.com/) out of the box.
</Note>

View File

@@ -4,22 +4,8 @@ export const metadata = {
# {metadata.title}
<Note type="soon">
Admin customizations are coming soon.
</Note>
In this chapter, you'll find some tips for your admin development.
## Sending Requests to API Routes
To send requests to your API routes in your admin customizations, its highly recommended to use the Medusa React or Medusa JS Client packages.
Check out their references for more details on available hooks or methods and how to use them.
---
## Routing Functionalities
To navigate or link to other pages, or use other routing functionalities, use the [react-router-dom](https://reactrouter.com/en/main) package:
@@ -30,40 +16,34 @@ npm install react-router-dom
For example:
```tsx title="src/admin/widgets/product-widget.tsx" highlights={[["18", "Link", "Add a link to another page."]]}
import type {
WidgetConfig,
ProductDetailsWidgetProps,
} from "@medusajs/admin"
import { Container, Heading, Button } from "@medusajs/ui"
export const highlights = [
["9", "Link", "Add a link to another page"],
["9", '"/orders', "Add the path without the `/app` prefix."]
]
```tsx title="src/admin/widgets/product-widget.tsx" highlights={highlights}
import { defineWidgetConfig } from "@medusajs/admin-shared"
import { Container } from "@medusajs/ui"
import { Link } from "react-router-dom"
// The widget
const ProductWidget = ({
product,
}: ProductDetailsWidgetProps) => {
const ProductWidget = () => {
return (
<Container>
<Heading level="h2">
Product Widget {product.title}
</Heading>
<Button className="mt-3" variant="transparent">
<Link to={"/a/orders"}>View Orders</Link>
</Button>
<Link to={"/orders"}>View Orders</Link>
</Container>
)
}
// The widget's configurations
export const config: WidgetConfig = {
export const config = defineWidgetConfig({
zone: "product.details.after",
}
})
export default ProductWidget
```
This adds a widget in a product's details page with a link to the Orders page.
This adds a widget in a product's details page with a link to the Orders page. The link's path must be without the `/app` prefix.
<Note title="Learn more">

View File

@@ -4,17 +4,11 @@ export const metadata = {
# {metadata.title}
<Note type="soon">
Admin customizations are coming soon.
</Note>
In this chapter, youll learn how to create a UI route in the admin dashboard.
## What is a UI Route?
A UI route is a React Component that adds a custom new page to your admin dashboard. The UI Route can be shown in the sidebar or added as a nested page.
A UI route is a React Component that adds a new page to your admin dashboard. The UI Route can be shown in the sidebar or added as a nested page.
For example, you may add a new page to manage product reviews.
@@ -34,7 +28,7 @@ const CustomPage = () => {
export default CustomPage
```
The new pages path is the files path relative to `src/admin/routes` and prefixed with `/a`. So, the above UI route is a new page added at the path `localhost:7001/a/custom`.
The new pages path is the files path relative to `src/admin/routes`. So, the above UI route is a new page added at the path `localhost:9000/app/custom`.
### Test the UI Route
@@ -44,7 +38,43 @@ To test the UI route, start the Medusa application:
npm run dev
```
Then, after logging into the admin dashboard, open the page `localhost:7001/a/custom` to see your custom page.
Then, after logging into the admin dashboard, open the page `localhost:9000/app/custom` to see your custom page.
---
## Show UI Route in the Sidebar
A UI route file can export a configuration object that indicates a new item must be added in the sidebar linking to the new UI route.
For example:
export const highlights = [
["14", "label", "The label of the UI route's sidebar item."],
["15", "icon", "The icon of the UI route's sidebar item."]
]
```tsx title="src/admin/routes/custom/page.tsx" highlights={[["21"], ["22"], ["23"], ["24"], ["25"], ["26"]]}
import { defineRouteConfig } from "@medusajs/admin-shared";
import { ChatBubbleLeftRight } from "@medusajs/icons"
const CustomPage = () => {
return <div>This is my custom route</div>
}
export const config = defineRouteConfig({
label: "Custom Route",
icon: ChatBubbleLeftRight,
})
export default CustomPage
```
The configuration object is creaetd by the `defineRouteConfig` function imported from `@medusajs/admin-shared`. It accepts the following properties:
- `label`: the new sidebar items label.
- `icon`: an optional React component that acts as an icon in the sidebar.
The above example adds a new sidebar item with the label `Custom Route` and an icon from the [Medusa UI Icons package](!ui!/icons/overview).
---
@@ -55,104 +85,50 @@ Similar to Widgets, its highly recommended that you use the [Medusa UI packag
For example, you can rewrite the above UI route to the following:
```tsx title="src/admin/routes/custom/page.tsx"
import { defineRouteConfig } from "@medusajs/admin-shared"
import { ChatBubbleLeftRight } from "@medusajs/icons"
import { Container } from "@medusajs/ui"
const CustomPage = () => {
return <Container>This is my custom route</Container>
}
export const config = defineRouteConfig({
label: "Custom Route",
icon: ChatBubbleLeftRight,
})
export default CustomPage
```
---
## UI Route Props
## Create Settings Page
A UI Route receives a `notify` prop, which is an object having the following properties:
- `success`: a function that shows a success toast message.
- `error`: a function that shows an error toast message.
- `warn`: a function that shows a warning toast message.
- `info`: a function that shows an info toast message.
Each of these functions accepts two parameters: the messages title and the messages content.
To create a page under the settings section of the admin dashboard, create the UI route file under the path `src/admin/routes/settings`.
For example:
```tsx title="src/admin/routes/custom/page.tsx" highlights={[["10", "success", "Show a success toast message on the click of a button."]]}
import { RouteProps } from "@medusajs/admin"
import { Container, Text, Button } from "@medusajs/ui"
```tsx title="src/admin/routes/settings/custom/page.tsx"
import { defineRouteConfig } from "@medusajs/admin-shared"
import { Container, Heading } from "@medusajs/ui"
const CustomPage = ({ notify }: RouteProps) => {
const CustomSettingPage = () => {
return (
<Container>
<Text>This is my custom route</Text>
<Button
onClick={() =>
notify.success("Success!", "You clicked the button!")
}
className="mt-3"
>
Click me
</Button>
<Heading level="h1">Custom Setting Page</Heading>
</Container>
)
}
export default CustomPage
export const config = defineRouteConfig({
label: "Custom",
})
export default CustomSettingPage;
```
<Note title="Tip">
Admin UI Routes support [Tailwind CSS](https://tailwindcss.com/) out of the box.
</Note>
---
## Show UI Route in the Sidebar
A UI route file can export a configuration object that indicates a new item must be added in the sidebar linking to the new UI route.
The configuration object has the property `link`, which is an object having the following properties:
- `label`: the new sidebar items label.
- `icon`: an optional React component that acts as an icon in the sidebar. If not provided, a default icon is used.
For example:
```tsx title="src/admin/routes/custom/page.tsx" highlights={[["21"], ["22"], ["23"], ["24"], ["25"], ["26"]]}
import { RouteConfig, RouteProps } from "@medusajs/admin"
import { Container, Text, Button } from "@medusajs/ui"
import { ChatBubbleLeftRight } from "@medusajs/icons"
const CustomPage = ({ notify }: RouteProps) => {
return (
<Container>
<Text>This is my custom route</Text>
<Button
onClick={() =>
notify.success("Success!", "You clicked the button!")
}
className="mt-3"
>
Click me
</Button>
</Container>
)
}
export const config: RouteConfig = {
link: {
label: "Custom Route",
icon: ChatBubbleLeftRight,
},
}
export default CustomPage
```
This adds a new sidebar item with the label `Custom Route` and an icon from the [Medusa UI Icons package](https://docs.medusajs.com/ui/icons/overview).
This adds a page under the path `/app/settings/custom`. An item is also added to the settings sidebar with the label `Custom`.
---
@@ -179,4 +155,6 @@ const CustomPage = () => {
}
export default CustomPage
```
```
If you run the Medusa application and go to `localhost:9000/app/custom/123`, you'll see `123` printed in the page.

View File

@@ -6,12 +6,6 @@ export const metadata = {
# {metadata.title}
<Note type="soon">
Admin customizations are coming soon.
</Note>
In this chapter, youll learn more about widgets and how to use them.
## What is an Admin Widget?
@@ -28,8 +22,13 @@ A widget is created in a file under the `src/admin/widgets` directory. The file
For example, create the file `src/admin/widgets/product-widget.tsx` with the following content:
```tsx title="src/admin/widgets/product-widget.tsx" highlights={[["4", "ProductWidget", "The React component of the product widget."], ["14", "", "The zone to inject the widget to."]]}
import type { WidgetConfig } from "@medusajs/admin"
export const widgetHighlights = [
["4", "ProductWidget", "The React component of the product widget."],
["14", "zone", "The zone to inject the widget to."]
]
```tsx title="src/admin/widgets/product-widget.tsx" highlights={widgetHighlights}
import { defineWidgetConfig } from "@medusajs/admin-shared"
// The widget
const ProductWidget = () => {
@@ -41,16 +40,20 @@ const ProductWidget = () => {
}
// The widget's configurations
export const config: WidgetConfig = {
export const config = defineWidgetConfig({
zone: "product.details.after",
}
})
export default ProductWidget
```
The widget only shows the heading `Product Widget`.
In the exported widgets configurations, you must specify the zone to inject the widget into. The `zone` property can be a string or an array of strings, each being the name of the injection zone.
Use the `defineWidgetConfig` function imported from `@medusajs/admin-shared` to create and export the widget's configurations.
The function accepts as a parameter an object with the following property:
- `zone`: A string or an array of strings, each being the name of the zone to inject the widget into.
In the example above, the widget is injected after a products details.
@@ -66,6 +69,37 @@ Then, open a products details page. Youll find your custom widget at the b
---
## Detail Widget Props
Widgets that are injected into a details page (for example, `product.details.after`) receive a `data` prop, which is the main data of the details page (for example, the product object).
For example:
```tsx title="src/admin/widgets/product-widget.tsx" highlights={[["5"]]}
import { defineWidgetConfig } from "@medusajs/admin-shared"
import { DetailWidgetProps, AdminProduct } from "@medusajs/types"
const ProductWidget = ({
data
}: DetailWidgetProps<AdminProduct>) => {
return (
<div>
<h2>Product Widget {data.title}</h2>
</div>
)
}
export const config = defineWidgetConfig({
zone: "product.details.after",
})
export default ProductWidget
```
Notice that the type of the props is `DetailWidgetProps`, which accepts as a type argument the expected type of the data.
---
## Using UI Components
Its highly recommended that you use the [Medusa UI package](https://docs.medusajs.com/ui) to match your widgets design with the rest of the Medusa Admin.
@@ -73,7 +107,7 @@ Its highly recommended that you use the [Medusa UI package](https://docs.medu
For example, you can rewrite the above component to the following:
```tsx title="src/admin/widgets/product-widget.tsx"
import type { WidgetConfig } from "@medusajs/admin"
import { defineWidgetConfig } from "@medusajs/admin-shared"
import { Container, Heading } from "@medusajs/ui"
const ProductWidget = () => {
@@ -84,72 +118,16 @@ const ProductWidget = () => {
)
}
export const config: WidgetConfig = {
export const config: WidgetConfig = defineWidgetConfig({
zone: "product.details.after",
}
})
export default ProductWidget
```
---
## Widget Props
A widget receives a `notify` prop, which is an object having the following properties:
- `success`: a function that shows a success toast message.
- `error`: a function that shows an error toast message.
- `warn`: a function that shows a warning toast message.
- `info`: a function that shows an info toast message.
Each of these functions accepts two parameters: the messages title, and the messages content.
In addition, some injection zones provide additional props based on the pages context.
For example, you can rewrite the above widget to the following:
```tsx title="src/admin/widgets/product-widget.tsx" highlights={[["14", "product.title", "Show the product's title."], ["18", "success", "Show a success toast message on the click of a button."]]}
import type {
WidgetConfig,
ProductDetailsWidgetProps,
} from "@medusajs/admin"
import { Container, Heading, Button } from "@medusajs/ui"
const ProductWidget = ({
notify,
product,
}: ProductDetailsWidgetProps) => {
return (
<Container>
<Heading level="h2">
Product Widget {product.title}
</Heading>
<Button
onClick={() =>
notify.success("Success!", "You clicked the button!")
}
className="mt-3"
>
Click me
</Button>
</Container>
)
}
export const config: WidgetConfig = {
zone: "product.details.after",
}
export default ProductWidget
```
Since the widget is in the products details page, it receives the product as a prop. The widget now shows the title of the product in the header.
It also shows a button that, when you click, shows a success toast message.
<Note title="Tip">
Admin Widgets support [Tailwind CSS](https://tailwindcss.com/) out of the box.
Admin Widgets also support [Tailwind CSS](https://tailwindcss.com/) out of the box.
</Note>

View File

@@ -43,15 +43,12 @@ The function receives as a parameter an object having a `container` property, wh
## How to Run Custom CLI Script?
To run the custom CLI script, `build` your code then run the `exec` command:
To run the custom CLI script, run the Medusa CLI's `exec` command:
```bash npm2yarn
npm run build
npx medusa exec ./dist/scripts/my-script.js
npx medusa exec ./src/scripts/my-script.ts
```
Notice that you pass the path to the file in the `dist` directory.
---
## Custom CLI Script Arguments
@@ -73,6 +70,5 @@ export default async function myScript ({
Then, pass the arguments in the `exec` command after the file path:
```bash npm2yarn
npm run build
npx medusa exec ./dist/scripts/my-script.js arg1 arg2
```
npx medusa exec ./src/scripts/my-script.ts arg1 arg2
```

View File

@@ -6,19 +6,13 @@ export const metadata = {
In this chapter, youll learn how to customize the Medusa Admin dashboard.
<Note type="soon">
Admin customizations are coming soon.
</Note>
## Overview
The Medusa Admin is an admin dashboard that merchants use to manage their store's data.
You can extend the Medusa Admin to add widgets and new pages. Your customizations interact with API routes to provide merchants with custom functionalities.
The Medusa Admin is installed in your Medusa application and runs at port `7001` when you start the Medusa application.
The Medusa Admin is installed in your Medusa application and runs at the path `/app` when you start the Medusa application.
---
@@ -29,7 +23,7 @@ A widget is a React component that can be injected into an existing page in the
For example, create the file `src/admin/widgets/product-widget.tsx` with the following content:
```tsx title="src/admin/widgets/product-widget.tsx"
import type { WidgetConfig } from "@medusajs/admin"
import { defineWidgetConfig } from "@medusajs/admin-shared"
const ProductWidget = () => {
return (
@@ -39,9 +33,9 @@ const ProductWidget = () => {
)
}
export const config: WidgetConfig = {
export const config = defineWidgetConfig({
zone: "product.details.after",
}
})
export default ProductWidget
```

View File

@@ -216,18 +216,10 @@ export const sidebar = sidebarAttachHrefCommonOptions(
path: "/advanced-development/admin/ui-routes",
title: "Admin UI Routes",
},
{
path: "/advanced-development/admin/setting-pages",
title: "Admin Setting Pages",
},
{
path: "/advanced-development/admin/tips",
title: "Tips",
},
{
path: "/advanced-development/admin/onboarding-example",
title: "Example: Onboarding Widget",
},
],
},
],

File diff suppressed because it is too large Load Diff

View File

@@ -1,400 +0,0 @@
import { Table, TypeList } from "docs-ui"
export const metadata = {
title: `Medusa Admin Configurations`,
}
# {metadata.title}
You can configure the Medusa Admin plugin to change its PORT, the Medusa server's URL, and more. You can also extend the Webpack configurations.
## Plugin Options
The plugin accepts the following options:
```js title="medusa-config.js"
const plugins = [
// ...
{
resolve: "@medusajs/admin",
/** @type {import('@medusajs/admin').PluginOptions} */
options: {
serve: true,
autoRebuild: true,
backend: "https://example.com",
path: "/app",
outDir: "build",
develop: {
open: true,
port: 7001,
logLevel: "error",
stats: "normal",
allowedHosts: "auto",
webSocketURL: undefined,
},
},
},
]
```
<TypeList types={[
{
name: "serve",
type: "boolean",
optional: true,
defaultValue: "true",
description: "Whether to serve the admin dashboard when the Medusa backend starts. If set to `false`, you can serve the admin dashboard using the [dev command](#develop-command-options).",
expandable: false,
children: []
},
{
name: "autoRebuild",
type: "boolean",
optional: true,
defaultValue: "false",
description: "Whether the admin UI should be rebuilt if there are any changes or if a missing build is detected when the backend starts. If not set, you must [manually build the admin dashboard](#build-command-options).",
expandable: false,
children: []
},
{
name: "backend",
type: "string",
optional: true,
defaultValue: "",
description: "The URL of the Medusa backend. Its value is only used if the `serve` option is set to `false`.",
expandable: false,
children: []
},
{
name: "path",
type: "string",
optional: true,
defaultValue: "/app",
description: "The path the admin server should run on when running the Medusa backend in production. It must be prefixed with a slash `/`, but it can't end with a `/`, which throws an error. It also can't be one of the reserved paths: \"admin\" and \"store\".",
expandable: false,
children: []
},
{
name: "outDir",
type: "string",
optional: true,
defaultValue: "",
description: "The directory to output the admin build to. By default, the plugin builds the admin to the `build` directory in the root of the Medusa backend directory.",
expandable: false,
children: []
},
{
name: "develop",
type: "object",
optional: true,
defaultValue: "",
description: "Options for the admin development server.",
expandable: false,
children: [
{
name: "open",
type: "boolean",
optional: true,
defaultValue: "true",
description: "Whether the browser should be opened when the admin development server starts.",
expandable: false,
children: []
},
{
name: "port",
type: "number",
optional: true,
defaultValue: "7001",
description: "The port the admin dashboard runs on.",
expandable: false,
children: []
},
{
name: "logLevel",
type: "\"error\" \\| \"none\" \\| \"warn\" \\| \"info\" \\| \"log\" \\| \"verbose\"",
optional: true,
defaultValue: "error",
description: "The log level of the admin development server.",
expandable: false,
children: []
},
{
name: "stats",
type: "\"normal\" \\| \"debug\"",
optional: true,
defaultValue: "normal",
description: "The verbosity of the admin development server.",
expandable: false,
children: []
},
{
name: "allowedHosts",
type: "\"auto\" \\| \"all\" \\| string[]",
optional: true,
defaultValue: "auto",
description: "The development server's allowed hosts.",
expandable: false,
children: []
},
{
name: "webSocketURL",
type: "string \\| object \\| undefined",
optional: true,
defaultValue: "",
description: "The URL to a web socket server",
expandable: false,
children: [
{
name: "hostname",
type: "string",
optional: true,
defaultValue: "",
description: "The web socket's hostname.",
expandable: false,
children: []
},
{
name: "password",
type: "string",
optional: true,
defaultValue: "",
description: "The web socket's password.",
expandable: false,
children: []
},
{
name: "path name",
type: "string",
optional: true,
defaultValue: "",
description: "The web socket's path name.",
expandable: false,
children: []
},
{
name: "port",
type: "string",
optional: true,
defaultValue: "",
description: "The web socket's port.",
expandable: false,
children: []
},
{
name: "username",
type: "string",
optional: true,
defaultValue: "",
description: "The web socket's username.",
expandable: false,
children: []
},
]
},
]
}
]} sectionTitle="Plugin Options" />
---
## Admin CLI Commands
The `medusa-admin` CLI tool is installed in your Medusa application. It's used within the `package.json`'s scripts to build admin assets.
### build
The `build` command in the admin CLI allows you to manually build the admin dashboard. For example:
```json title="package.json"
{
"scripts": {
// other scripts...
"build:admin": "medusa-admin build"
}
}
```
#### Options
<Table>
<Table.Header>
<Table.Row>
<Table.HeaderCell>Option</Table.HeaderCell>
<Table.HeaderCell>Description</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
<Table.Row>
<Table.Cell>
`--deployment`
</Table.Cell>
<Table.Cell>
Build admin assets for deployment. When this option is added, plugin options are not loaded from `medusa-config.js` anymore, and
the backend URL is loaded from the `MEDUSA_ADMIN_BACKEND_URL` environment variable.
</Table.Cell>
</Table.Row>
</Table.Body>
</Table>
### develop
The `develop` command in the admin CLI allows you to run the admin dashboard in development separately from the Medusa application. For example:
```json title="package.json"
{
"scripts": {
// other scripts...
"dev:admin": "medusa-admin develop"
}
}
```
#### Options
<Table>
<Table.Header>
<Table.Row>
<Table.HeaderCell>Option</Table.HeaderCell>
<Table.HeaderCell>Description</Table.HeaderCell>
<Table.HeaderCell>Default</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
<Table.Row>
<Table.Cell>
`--backend <url>`, `-b <url>`
</Table.Cell>
<Table.Cell>
The URL of the Medusa backend.
</Table.Cell>
<Table.Cell>
The value of the environment variable `MEDUSA_ADMIN_BACKEND_URL`
</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell>
`--port <url>`, `-p <url>`
</Table.Cell>
<Table.Cell>
The port to run the admin on.
</Table.Cell>
<Table.Cell>
`7001`
</Table.Cell>
</Table.Row>
</Table.Body>
</Table>
## Change the Medusa Application URL
### In Development
To change the Medusa application's URL that the admin sends request to, disable the `serve` plugin option and set the `backend` option to the new URL.
However, this requires you to also set-up the [develop command](#develop-command-options) as the admin will no longer start with the Medusa application.
For example:
```js title="medusa-config.js"
const plugins = [
// ...
{
resolve: "@medusajs/admin",
/** @type {import('@medusajs/admin').PluginOptions} */
options: {
serve: false,
backend: "http://localhost:9001",
// other options...
},
},
]
```
### In Production
<Note>
This assumes that you've deployed the admin separately and you're passing the `--deployment` option to the [build command](#build-command-options).
</Note>
To change the backend's URL that the admin sends request to, set the environment variable `MEDUSA_ADMIN_BACKEND_URL` to the backend's URL.
For example:
```bash
MEDUSA_ADMIN_BACKEND_URL=https://example.com
```
---
## Custom Environment Variables
To set environment variables that you want to access in your admin dashboard's customizations (such as in [widgets](!docs!/advanced-development/admin/widgets) or [UI routes](!docs!/advanced-development/admin/ui-routes)), your environment variables must be prefixed with `MEDUSA_ADMIN_`. Otherwise, it won't be loaded within the admin.
For example:
```bash
MEDUSA_ADMIN_CUSTOM_API_KEY=123...
```
---
## Custom Webpack Configurations
<Note type="warning">
This is an advanced feature and requires knowledge of configuring webpack. If configured wrongly, it may lead to the admin application breaking.
</Note>
<Note>
Plugins can't include webpack customizations.
</Note>
The Medusa Admin uses [Webpack](https://webpack.js.org/) to define the configurations for both the Medusa Admin plugin and your customizations.
You can extend the default webpack configurations defined in the admin plugin to add your custom configurations, such as to support styling your extensions with CSS Modules.
To do that, create the file `src/admin/webpack.config.js` that uses the `withCustomWebpackConfig` method imported from `@medusajs/admin` to export the extended configurations:
```js title="src/admin/webpack.config.js"
import { withCustomWebpackConfig } from "@medusajs/admin"
export default withCustomWebpackConfig((config, webpack) => {
config.plugins.push(
new webpack.DefinePlugin({
"process.env": {
NODE_ENV: JSON.stringify("production"),
API_URL:
JSON.stringify("https://api.medusa-commerce.com"),
},
})
)
return config
})
```
The method `withCustomWebpackConfig` accepts a callback function that must return an object of [webpack configuration](https://webpack.js.org/configuration/). The callback function accepts two parameters:
1. The first parameter is an object that holds the default webpack configuration. Add your configurations to this object, then return it. Not returning the default configurations breaks the application.
2. The second parameter is the webpack instance.

View File

@@ -588,7 +588,7 @@ npx medusa exec [file] [args...]
</Table.Cell>
<Table.Cell>
The path to a JavaScript file holding the function to execute.
The path to the TypeScript or JavaScript file holding the function to execute.
</Table.Cell>
<Table.Cell>

View File

@@ -1,18 +0,0 @@
export const metadata = {
title: `Signing in to Medusa Admin`,
}
# {metadata.title}
If you've created a new Medusa backend and used the `seed` command, the default credentials are:
```bash noReport
email: admin@medusa-test.com
password: supersecret
```
Alternatively, you can create your own users using the Medusa CLI tool:
```bash
npx medusa user -e some@email.com -p somepassword
```

View File

@@ -1,93 +0,0 @@
export const metadata = {
title: `Admin Webpack Build Error`,
}
# {metadata.title}
If you run the `build` command in your backend and you get an error message during the admin build process similar to the following:
```bash noReport noCopy
The left-hand side of an assignment expression must be a variable or a property access.
```
Make sure that in your admin customizations (widget, UI route, or settings page) you're not using a type imported from `@medusajs/medusa`.
This is often the case if you're using a type or an enum necessary for a request sent with the JS Client or Medusa React library.
For example:
```ts
import {
Region,
ShippingOptionPriceType,
} from "@medusajs/medusa"
import type Medusa from "@medusajs/medusa-js"
export default async function prepareShippingOptions(
client: Medusa,
region: Region
) {
let {
shipping_options,
} = await client.admin.shippingOptions.list({
region_id: region.id,
})
if (!shipping_options.length) {
shipping_options = [(
await client.admin.shippingOptions.create({
"name": "PostFake Standard",
"region_id": region.id,
"provider_id": "manual",
"data": {
"id": "manual-fulfillment",
},
// THIS CAUSES THE ERROR
"price_type": ShippingOptionPriceType.FLAT_RATE,
"amount": 1000,
}
)).shipping_option]
}
return shipping_options
}
```
In this case, you're using the `ShippingOptionPriceType` type to send a request with the JS Client.
Instead, change it to the string value. If you get a TypeScript error, you can add `// @ts-ignore` before the line:
```ts
import {
Region,
ShippingOptionPriceType,
} from "@medusajs/medusa"
import type Medusa from "@medusajs/medusa-js"
export default async function prepareShippingOptions(
client: Medusa,
region: Region
) {
let {
shipping_options,
} = await client.admin.shippingOptions.list({
region_id: region.id,
})
if (!shipping_options.length) {
shipping_options = [(
await client.admin.shippingOptions.create({
"name": "PostFake Standard",
"region_id": region.id,
"provider_id": "manual",
"data": {
"id": "manual-fulfillment",
},
// @ts-expect-error can't use type from core
"price_type": "flat_rate",
"amount": 1000,
}
)).shipping_option]
}
return shipping_options
}
```

View File

@@ -1668,10 +1668,6 @@ export const sidebar = sidebarAttachHrefCommonOptions([
path: "/references/medusa-config",
title: "Medusa Application",
},
// {
// path: "/configurations/medusa-admin",
// title: "Medusa Admin",
// },
],
},
{
@@ -1800,20 +1796,6 @@ export const sidebar = sidebarAttachHrefCommonOptions([
},
],
},
{
title: "Medusa Admin",
hasTitleStyling: true,
children: [
{
path: "/troubleshooting/admin-sign-in",
title: "Signing In",
},
{
path: "/troubleshooting/admin-custom-hooks-error",
title: "Custom Hooks Error",
},
],
},
],
},
],