@mercurjs/docs 2.2.0-canary.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -0
- package/content/blocks.mdx +209 -0
- package/content/learn/architecture.mdx +215 -0
- package/content/learn/attributes.mdx +89 -0
- package/content/learn/blocks.mdx +99 -0
- package/content/learn/commissions.mdx +175 -0
- package/content/learn/concepts.mdx +84 -0
- package/content/learn/installation.mdx +117 -0
- package/content/learn/introduction.mdx +71 -0
- package/content/learn/offers.mdx +78 -0
- package/content/learn/order-groups.mdx +114 -0
- package/content/learn/payouts.mdx +175 -0
- package/content/learn/product-requests.mdx +82 -0
- package/content/learn/products.mdx +79 -0
- package/content/learn/registry.mdx +155 -0
- package/content/learn/seller-members.mdx +62 -0
- package/content/learn/sellers.mdx +118 -0
- package/content/migration/from-1-x-to-2-0.mdx +152 -0
- package/content/migration/from-2-0-to-2-1.mdx +105 -0
- package/content/migration/overview.mdx +58 -0
- package/content/references/api/admin/commission-rates/batch-commission-rules.mdx +70 -0
- package/content/references/api/admin/commission-rates/create-commission-rate.mdx +95 -0
- package/content/references/api/admin/commission-rates/delete-commission-rate.mdx +40 -0
- package/content/references/api/admin/commission-rates/list-commission-rates.mdx +92 -0
- package/content/references/api/admin/commission-rates/retrieve-commission-rate.mdx +70 -0
- package/content/references/api/admin/commission-rates/update-commission-rate.mdx +84 -0
- package/content/references/api/admin/members/list-members.mdx +61 -0
- package/content/references/api/admin/offers/batch-create-offers.mdx +130 -0
- package/content/references/api/admin/offers/delete-offer.mdx +40 -0
- package/content/references/api/admin/offers/list-offers.mdx +106 -0
- package/content/references/api/admin/offers/retrieve-offer.mdx +82 -0
- package/content/references/api/admin/order-groups/list-order-groups.mdx +77 -0
- package/content/references/api/admin/order-groups/retrieve-order-group.mdx +56 -0
- package/content/references/api/admin/orders/get-order-commission-lines.mdx +65 -0
- package/content/references/api/admin/orders/get-order-order-group.mdx +56 -0
- package/content/references/api/admin/orders/list-orders.mdx +79 -0
- package/content/references/api/admin/payouts/list-payouts.mdx +75 -0
- package/content/references/api/admin/payouts/retrieve-payout.mdx +62 -0
- package/content/references/api/admin/product-attributes/create-attribute-value.mdx +76 -0
- package/content/references/api/admin/product-attributes/create-product-attribute.mdx +99 -0
- package/content/references/api/admin/product-attributes/delete-attribute-value.mdx +52 -0
- package/content/references/api/admin/product-attributes/delete-product-attribute.mdx +40 -0
- package/content/references/api/admin/product-attributes/list-product-attributes.mdx +91 -0
- package/content/references/api/admin/product-attributes/retrieve-product-attribute.mdx +81 -0
- package/content/references/api/admin/product-attributes/update-attribute-value.mdx +66 -0
- package/content/references/api/admin/product-attributes/update-product-attribute.mdx +76 -0
- package/content/references/api/admin/product-changes/cancel-product-change.mdx +68 -0
- package/content/references/api/admin/product-changes/confirm-product-change.mdx +47 -0
- package/content/references/api/admin/products/batch-product-attributes.mdx +96 -0
- package/content/references/api/admin/products/confirm-product.mdx +59 -0
- package/content/references/api/admin/products/create-product-variant.mdx +78 -0
- package/content/references/api/admin/products/create-product.mdx +169 -0
- package/content/references/api/admin/products/delete-product-variant.mdx +48 -0
- package/content/references/api/admin/products/delete-product.mdx +40 -0
- package/content/references/api/admin/products/list-product-variants.mdx +91 -0
- package/content/references/api/admin/products/list-products.mdx +109 -0
- package/content/references/api/admin/products/preview-product.mdx +78 -0
- package/content/references/api/admin/products/reject-product.mdx +59 -0
- package/content/references/api/admin/products/request-product-changes.mdx +59 -0
- package/content/references/api/admin/products/retrieve-product-variant.mdx +73 -0
- package/content/references/api/admin/products/retrieve-product.mdx +96 -0
- package/content/references/api/admin/products/set-product-sellers.mdx +47 -0
- package/content/references/api/admin/products/update-product-variant.mdx +89 -0
- package/content/references/api/admin/products/update-product.mdx +133 -0
- package/content/references/api/admin/sellers/add-seller-member.mdx +63 -0
- package/content/references/api/admin/sellers/approve-seller.mdx +54 -0
- package/content/references/api/admin/sellers/create-seller.mdx +100 -0
- package/content/references/api/admin/sellers/delete-member-invite.mdx +42 -0
- package/content/references/api/admin/sellers/delete-professional-details.mdx +52 -0
- package/content/references/api/admin/sellers/invite-seller-member.mdx +63 -0
- package/content/references/api/admin/sellers/list-member-invites.mdx +71 -0
- package/content/references/api/admin/sellers/list-seller-members.mdx +71 -0
- package/content/references/api/admin/sellers/list-seller-products.mdx +85 -0
- package/content/references/api/admin/sellers/list-sellers.mdx +96 -0
- package/content/references/api/admin/sellers/remove-seller-member.mdx +42 -0
- package/content/references/api/admin/sellers/resend-member-invite.mdx +55 -0
- package/content/references/api/admin/sellers/retrieve-seller.mdx +81 -0
- package/content/references/api/admin/sellers/suspend-seller.mdx +60 -0
- package/content/references/api/admin/sellers/terminate-seller.mdx +60 -0
- package/content/references/api/admin/sellers/unsuspend-seller.mdx +52 -0
- package/content/references/api/admin/sellers/unterminate-seller.mdx +52 -0
- package/content/references/api/admin/sellers/update-seller.mdx +83 -0
- package/content/references/api/admin/sellers/upsert-payment-details.mdx +88 -0
- package/content/references/api/admin/sellers/upsert-professional-details.mdx +78 -0
- package/content/references/api/admin/sellers/upsert-seller-address.mdx +91 -0
- package/content/references/api/admin.mdx +134 -0
- package/content/references/api/conventions.mdx +109 -0
- package/content/references/api/store/carts/add-line-item.mdx +115 -0
- package/content/references/api/store/carts/add-shipping-methods.mdx +84 -0
- package/content/references/api/store/carts/apply-promotions.mdx +83 -0
- package/content/references/api/store/carts/complete-cart.mdx +98 -0
- package/content/references/api/store/offers/list-offers.mdx +161 -0
- package/content/references/api/store/offers/retrieve-offer.mdx +112 -0
- package/content/references/api/store/order-groups/list-order-groups.mdx +105 -0
- package/content/references/api/store/order-groups/retrieve-order-group.mdx +78 -0
- package/content/references/api/store/product-attributes/list-product-attributes.mdx +134 -0
- package/content/references/api/store/product-attributes/retrieve-product-attribute.mdx +78 -0
- package/content/references/api/store/product-categories/list-product-categories.mdx +126 -0
- package/content/references/api/store/product-categories/retrieve-product-category.mdx +79 -0
- package/content/references/api/store/products/list-products.mdx +184 -0
- package/content/references/api/store/products/retrieve-product.mdx +107 -0
- package/content/references/api/store/search/search.mdx +136 -0
- package/content/references/api/store/sellers/list-sellers.mdx +105 -0
- package/content/references/api/store/sellers/retrieve-seller.mdx +62 -0
- package/content/references/api/store/shipping-options/list-shipping-options.mdx +74 -0
- package/content/references/api/store.mdx +67 -0
- package/content/references/api/vendor/members/accept-member-invite.mdx +65 -0
- package/content/references/api/vendor/members/retrieve-current-member.mdx +51 -0
- package/content/references/api/vendor/members/update-current-member.mdx +70 -0
- package/content/references/api/vendor/offers/batch-create-offers.mdx +123 -0
- package/content/references/api/vendor/offers/batch-offer-inventory-items.mdx +103 -0
- package/content/references/api/vendor/offers/create-offer.mdx +141 -0
- package/content/references/api/vendor/offers/delete-offer.mdx +51 -0
- package/content/references/api/vendor/offers/list-offers.mdx +125 -0
- package/content/references/api/vendor/offers/retrieve-offer.mdx +74 -0
- package/content/references/api/vendor/offers/update-offer.mdx +82 -0
- package/content/references/api/vendor/orders/cancel-fulfillment.mdx +63 -0
- package/content/references/api/vendor/orders/cancel-order.mdx +56 -0
- package/content/references/api/vendor/orders/complete-order.mdx +55 -0
- package/content/references/api/vendor/orders/create-fulfillment.mdx +76 -0
- package/content/references/api/vendor/orders/create-shipment.mdx +99 -0
- package/content/references/api/vendor/orders/get-order-commission-lines.mdx +66 -0
- package/content/references/api/vendor/orders/list-order-changes.mdx +75 -0
- package/content/references/api/vendor/orders/list-orders.mdx +103 -0
- package/content/references/api/vendor/orders/mark-fulfillment-delivered.mdx +62 -0
- package/content/references/api/vendor/orders/preview-order.mdx +65 -0
- package/content/references/api/vendor/orders/retrieve-order.mdx +84 -0
- package/content/references/api/vendor/payout-accounts/create-onboarding.mdx +68 -0
- package/content/references/api/vendor/payout-accounts/create-payout-account.mdx +59 -0
- package/content/references/api/vendor/payout-accounts/retrieve-payout-account-by-id.mdx +60 -0
- package/content/references/api/vendor/payout-accounts/retrieve-payout-account.mdx +77 -0
- package/content/references/api/vendor/payouts/list-payouts.mdx +90 -0
- package/content/references/api/vendor/payouts/retrieve-payout.mdx +63 -0
- package/content/references/api/vendor/product-attributes/list-product-attributes.mdx +135 -0
- package/content/references/api/vendor/product-attributes/retrieve-product-attribute.mdx +71 -0
- package/content/references/api/vendor/product-variants/list-variants.mdx +136 -0
- package/content/references/api/vendor/products/batch-product-attributes.mdx +104 -0
- package/content/references/api/vendor/products/cancel-product-change.mdx +62 -0
- package/content/references/api/vendor/products/create-product-variant.mdx +92 -0
- package/content/references/api/vendor/products/create-product.mdx +197 -0
- package/content/references/api/vendor/products/delete-product-variant.mdx +68 -0
- package/content/references/api/vendor/products/delete-product.mdx +62 -0
- package/content/references/api/vendor/products/list-product-variants.mdx +114 -0
- package/content/references/api/vendor/products/list-products.mdx +163 -0
- package/content/references/api/vendor/products/preview-product.mdx +61 -0
- package/content/references/api/vendor/products/retrieve-product-variant.mdx +76 -0
- package/content/references/api/vendor/products/retrieve-product.mdx +69 -0
- package/content/references/api/vendor/products/update-product-variant.mdx +104 -0
- package/content/references/api/vendor/products/update-product.mdx +148 -0
- package/content/references/api/vendor/sellers/create-seller.mdx +150 -0
- package/content/references/api/vendor/sellers/delete-professional-details.mdx +54 -0
- package/content/references/api/vendor/sellers/invite-seller-member.mdx +67 -0
- package/content/references/api/vendor/sellers/list-member-invites.mdx +82 -0
- package/content/references/api/vendor/sellers/list-seller-members.mdx +80 -0
- package/content/references/api/vendor/sellers/list-sellers.mdx +71 -0
- package/content/references/api/vendor/sellers/remove-seller-member.mdx +48 -0
- package/content/references/api/vendor/sellers/retrieve-current-seller-member.mdx +59 -0
- package/content/references/api/vendor/sellers/retrieve-current-seller.mdx +69 -0
- package/content/references/api/vendor/sellers/select-seller.mdx +44 -0
- package/content/references/api/vendor/sellers/update-current-seller.mdx +108 -0
- package/content/references/api/vendor/sellers/update-member-role.mdx +51 -0
- package/content/references/api/vendor/sellers/upsert-payment-details.mdx +74 -0
- package/content/references/api/vendor/sellers/upsert-professional-details.mdx +70 -0
- package/content/references/api/vendor/sellers/upsert-seller-address.mdx +81 -0
- package/content/references/api/vendor.mdx +150 -0
- package/content/references/configuration.mdx +155 -0
- package/content/references/modules/commission.mdx +106 -0
- package/content/references/modules/custom-fields.mdx +45 -0
- package/content/references/modules/media.mdx +55 -0
- package/content/references/modules/offer.mdx +64 -0
- package/content/references/modules/payout.mdx +121 -0
- package/content/references/modules/product-attribute.mdx +111 -0
- package/content/references/modules/product-edit.mdx +80 -0
- package/content/references/modules/search.mdx +112 -0
- package/content/references/modules/seller.mdx +175 -0
- package/content/references/overview.mdx +70 -0
- package/content/references/workflows/cart/add-seller-shipping-method-to-cart.mdx +44 -0
- package/content/references/workflows/cart/complete-cart-with-split-orders.mdx +36 -0
- package/content/references/workflows/cart/list-seller-shipping-options-for-cart.mdx +39 -0
- package/content/references/workflows/cart/update-cart-seller-promotions.mdx +42 -0
- package/content/references/workflows/commission/batch-commission-rules.mdx +45 -0
- package/content/references/workflows/commission/create-commission-rates.mdx +41 -0
- package/content/references/workflows/commission/delete-commission-rates.mdx +34 -0
- package/content/references/workflows/commission/refresh-order-commission-lines.mdx +30 -0
- package/content/references/workflows/commission/update-commission-rates.mdx +35 -0
- package/content/references/workflows/media/set-category-images.mdx +41 -0
- package/content/references/workflows/media/set-collection-images.mdx +41 -0
- package/content/references/workflows/member/accept-member-invite.mdx +33 -0
- package/content/references/workflows/member/add-seller-member.mdx +30 -0
- package/content/references/workflows/member/create-member-invites.mdx +34 -0
- package/content/references/workflows/member/delete-member-invite.mdx +24 -0
- package/content/references/workflows/member/remove-seller-member.mdx +28 -0
- package/content/references/workflows/member/resend-member-invite.mdx +28 -0
- package/content/references/workflows/member/update-member-role.mdx +28 -0
- package/content/references/workflows/member/update-member.mdx +35 -0
- package/content/references/workflows/offer/batch-offer-inventory-items.mdx +58 -0
- package/content/references/workflows/offer/create-offers.mdx +63 -0
- package/content/references/workflows/offer/delete-offers.mdx +35 -0
- package/content/references/workflows/offer/update-offers.mdx +51 -0
- package/content/references/workflows/order/cancel-order-fulfillment.mdx +34 -0
- package/content/references/workflows/order/confirm-claim-request.mdx +25 -0
- package/content/references/workflows/order/confirm-exchange-request.mdx +25 -0
- package/content/references/workflows/order/confirm-order-edit-request.mdx +25 -0
- package/content/references/workflows/order/confirm-return-receive.mdx +25 -0
- package/content/references/workflows/order/create-order-fulfillment.mdx +45 -0
- package/content/references/workflows/order-group/get-order-group-detail.mdx +29 -0
- package/content/references/workflows/order-group/get-order-groups-list.mdx +36 -0
- package/content/references/workflows/overview.mdx +72 -0
- package/content/references/workflows/payout/create-onboarding.mdx +36 -0
- package/content/references/workflows/payout/create-payout-account.mdx +33 -0
- package/content/references/workflows/payout/create-payout.mdx +30 -0
- package/content/references/workflows/payout/process-payout-for-webhook.mdx +32 -0
- package/content/references/workflows/product/confirm-products.mdx +46 -0
- package/content/references/workflows/product/create-products.mdx +63 -0
- package/content/references/workflows/product/link-sellers-to-product-category.mdx +40 -0
- package/content/references/workflows/product/link-sellers-to-product.mdx +40 -0
- package/content/references/workflows/product/reject-product.mdx +46 -0
- package/content/references/workflows/product/request-product-change.mdx +46 -0
- package/content/references/workflows/product-attribute/add-product-attributes-to-product.mdx +49 -0
- package/content/references/workflows/product-attribute/create-and-link-product-attributes-to-product.mdx +46 -0
- package/content/references/workflows/product-attribute/create-product-attribute-values.mdx +43 -0
- package/content/references/workflows/product-attribute/create-product-attributes.mdx +56 -0
- package/content/references/workflows/product-attribute/delete-product-attribute-values.mdx +30 -0
- package/content/references/workflows/product-attribute/delete-product-attributes.mdx +30 -0
- package/content/references/workflows/product-attribute/remove-product-attributes-from-product.mdx +29 -0
- package/content/references/workflows/product-attribute/update-product-attribute-values.mdx +44 -0
- package/content/references/workflows/product-attribute/update-product-attributes-on-product.mdx +41 -0
- package/content/references/workflows/product-attribute/update-product-attributes.mdx +48 -0
- package/content/references/workflows/product-attribute/upsert-product-attribute-values.mdx +43 -0
- package/content/references/workflows/product-edit/auto-confirm-product-change.mdx +39 -0
- package/content/references/workflows/product-edit/cancel-product-change.mdx +49 -0
- package/content/references/workflows/product-edit/confirm-product-change.mdx +57 -0
- package/content/references/workflows/product-edit/create-product-change.mdx +72 -0
- package/content/references/workflows/product-edit/reject-product-change.mdx +54 -0
- package/content/references/workflows/product-edit/stage-product-change.mdx +75 -0
- package/content/references/workflows/seller/approve-seller.mdx +34 -0
- package/content/references/workflows/seller/create-seller-account.mdx +59 -0
- package/content/references/workflows/seller/create-seller-defaults.mdx +22 -0
- package/content/references/workflows/seller/create-sellers.mdx +65 -0
- package/content/references/workflows/seller/delete-seller-professional-details.mdx +37 -0
- package/content/references/workflows/seller/delete-sellers.mdx +24 -0
- package/content/references/workflows/seller/invite-seller.mdx +28 -0
- package/content/references/workflows/seller/suspend-seller.mdx +35 -0
- package/content/references/workflows/seller/terminate-seller.mdx +35 -0
- package/content/references/workflows/seller/unsuspend-seller.mdx +34 -0
- package/content/references/workflows/seller/unterminate-seller.mdx +34 -0
- package/content/references/workflows/seller/update-seller-address.mdx +55 -0
- package/content/references/workflows/seller/update-seller-payment-details.mdx +52 -0
- package/content/references/workflows/seller/update-seller-professional-details.mdx +48 -0
- package/content/references/workflows/seller/update-sellers.mdx +57 -0
- package/content/resources/ai/llms.mdx +74 -0
- package/content/resources/ai/mcp.mdx +152 -0
- package/content/resources/ai/overview.mdx +97 -0
- package/content/resources/customization/custom-fields.mdx +182 -0
- package/content/resources/customization/extend-a-workflow.mdx +39 -0
- package/content/resources/customization/extending-panels.mdx +309 -0
- package/content/resources/deployment/medusa-cloud.mdx +167 -0
- package/content/resources/integrations/notifications.mdx +39 -0
- package/content/resources/integrations/search.mdx +122 -0
- package/content/resources/integrations/stripe-connect.mdx +395 -0
- package/content/resources/tutorials/add-a-block.mdx +74 -0
- package/content/resources/tutorials/attributes-and-variant-axes.mdx +111 -0
- package/content/resources/tutorials/build-a-block.mdx +134 -0
- package/content/resources/tutorials/configure-commissions.mdx +127 -0
- package/content/resources/tutorials/custom-api-route.mdx +142 -0
- package/content/resources/tutorials/custom-panel-page.mdx +78 -0
- package/content/resources/tutorials/first-marketplace.mdx +45 -0
- package/content/resources/tutorials/handle-product-requests.mdx +80 -0
- package/content/resources/tutorials/import-export-products.mdx +96 -0
- package/content/resources/tutorials/master-products-and-offers.mdx +89 -0
- package/content/resources/tutorials/recompose-a-page.mdx +129 -0
- package/content/resources/tutorials/replace-panel-components.mdx +116 -0
- package/content/resources/tutorials/seller-payouts-stripe.mdx +89 -0
- package/content/telemetry.mdx +67 -0
- package/content/tools/api-client.mdx +155 -0
- package/content/tools/cli.mdx +196 -0
- package/content/tools/dashboard-sdk.mdx +35 -0
- package/content/user-guide/admin/overview.mdx +23 -0
- package/content/user-guide/admin/stores.mdx +193 -0
- package/content/user-guide/vendor/overview.mdx +23 -0
- package/content/user-guide/vendor/stores.mdx +209 -0
- package/llms.txt +307 -0
- package/package.json +33 -0
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Extending Panels"
|
|
3
|
+
description: "Add pages, customize navigation, branding, and replace components in the admin and vendor panels."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Both the admin panel and vendor portal use the same SDK (`@mercurjs/dashboard-sdk`). Customization is file-based and convention-driven — you add pages by creating files, configure navigation through exports, and override components through config.
|
|
7
|
+
|
|
8
|
+
<Info>
|
|
9
|
+
**Mercur does not use Medusa's admin customization.** If you're coming from Medusa, forget `defineWidgetConfig`, `defineRouteConfig`, and widget injection zones — none of them exist here. Mercur ships its own admin **and** vendor panels, built on a shared extension framework with three mechanisms: **drop-in routes** (file-based pages that can also *replace* built-in pages), **compound-component re-composition** (every built-in page exposes its parts as slots), and **named layout overrides** (sidebar, topbar, store setup). The trade: instead of injecting widgets into fixed zones around a page Medusa controls, you compose the actual page — which is what makes a two-panel marketplace customizable without forking.
|
|
10
|
+
</Info>
|
|
11
|
+
|
|
12
|
+
## Choosing your extension mechanism
|
|
13
|
+
|
|
14
|
+
Junior-friendly rule of thumb: **adding something new? Drop in a route. Changing something that exists? Re-compose it. Changing the frame around every page? Override a component. Sharing it across projects? Make it a block.**
|
|
15
|
+
|
|
16
|
+
| You want to… | Use | Why it's the right tool |
|
|
17
|
+
|--------------|-----|------------------------|
|
|
18
|
+
| Add a new screen or feature | A drop-in `page.tsx` route | New URL, auto-registered, sidebar entry via the `config` export — see [Add a page](#add-a-page) |
|
|
19
|
+
| Change part of an existing page | A drop-in route **at the same path**, re-composing the page's compound slots | Your route replaces the built-in one; untouched slots keep all their behavior — see the [re-compose tutorial](/rc/resources/tutorials/recompose-a-page) |
|
|
20
|
+
| Change global chrome (sidebar, topbar, store setup) | A component override in the plugin config | One component, applied everywhere its slot renders — see [Replace components](#replace-components) |
|
|
21
|
+
| Reuse a feature across projects | A [block](/rc/learn/blocks) | Ships API + admin + vendor files installable with `mercurjs add` — see the [build-a-block tutorial](/rc/resources/tutorials/build-a-block) |
|
|
22
|
+
|
|
23
|
+
<Note>
|
|
24
|
+
The middle row is the one Medusa developers miss most. Because built-in pages are exported as compound components (e.g. `ProductListPage` from `@mercurjs/vendor/pages` with `Header`, `HeaderActions`, `DataTable` slots), "customize the products page" doesn't mean forking it — it means rendering it with your own composition and reusing the slots you don't change.
|
|
25
|
+
</Note>
|
|
26
|
+
|
|
27
|
+
## Set up
|
|
28
|
+
|
|
29
|
+
All configuration lives in the panel app's Vite config — there is no separate config file.
|
|
30
|
+
|
|
31
|
+
<Steps>
|
|
32
|
+
<Step title="Register the plugin">
|
|
33
|
+
Add `mercurDashboardPlugin` to the panel app's `vite.config.ts`. The only required option is `medusaConfigPath` — the plugin reads panel paths and ports from your API's Medusa config:
|
|
34
|
+
|
|
35
|
+
```typescript vite.config.ts
|
|
36
|
+
import { defineConfig } from 'vite'
|
|
37
|
+
import react from '@vitejs/plugin-react'
|
|
38
|
+
import { mercurDashboardPlugin } from '@mercurjs/dashboard-sdk'
|
|
39
|
+
|
|
40
|
+
export default defineConfig({
|
|
41
|
+
plugins: [
|
|
42
|
+
react(),
|
|
43
|
+
mercurDashboardPlugin({
|
|
44
|
+
medusaConfigPath: '../../packages/api/medusa-config.ts',
|
|
45
|
+
name: 'My Marketplace',
|
|
46
|
+
logo: 'https://example.com/logo.svg',
|
|
47
|
+
}),
|
|
48
|
+
],
|
|
49
|
+
})
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Projects created with `create-mercur-app` ship with this already wired for both panels.
|
|
53
|
+
</Step>
|
|
54
|
+
<Step title="Pass environment values explicitly">
|
|
55
|
+
The plugin doesn't read `.env` itself — load environment variables in `vite.config.ts` (e.g. with Vite's `loadEnv`) and pass them into the plugin options, as the starter template does with `backendUrl`.
|
|
56
|
+
</Step>
|
|
57
|
+
<Step title="Restart after config changes">
|
|
58
|
+
Options are applied at build time through virtual modules. Adding or removing routes hot-reloads automatically, but changes to the plugin options require a dev-server restart.
|
|
59
|
+
</Step>
|
|
60
|
+
</Steps>
|
|
61
|
+
|
|
62
|
+
### Configuration options
|
|
63
|
+
|
|
64
|
+
| Option | Type | Description |
|
|
65
|
+
|--------|------|-------------|
|
|
66
|
+
| `medusaConfigPath` | `string` | **Required.** Path to your API's `medusa-config.ts`, relative to the panel project root |
|
|
67
|
+
| `backendUrl` | `string` | Medusa backend URL (default: `http://localhost:9000`) |
|
|
68
|
+
| `vendorUrl` | `string` | Absolute vendor portal URL including its path prefix |
|
|
69
|
+
| `name` | `string` | Application name shown in the sidebar |
|
|
70
|
+
| `logo` | `string` | URL to a logo image |
|
|
71
|
+
| `components` | `object` | Component overrides (see [Replace components](#replace-components)) |
|
|
72
|
+
| `i18n` | `object` | Internationalization settings (`{ defaultLanguage }`) |
|
|
73
|
+
| `enableSellerRegistration` | `boolean` | Enable the public seller registration flow (vendor portal) |
|
|
74
|
+
| `imageLimit` | `number` | Max upload size for images in bytes (default: 2 MB) |
|
|
75
|
+
|
|
76
|
+
## Add a page
|
|
77
|
+
|
|
78
|
+
<Steps>
|
|
79
|
+
<Step title="Create the route file">
|
|
80
|
+
Create a `page.tsx` inside `src/routes/` and export a default React component. The route is determined by the file path:
|
|
81
|
+
|
|
82
|
+
```tsx src/routes/reviews/page.tsx
|
|
83
|
+
import { Star } from "@medusajs/icons"
|
|
84
|
+
import type { RouteConfig } from "@mercurjs/dashboard-sdk"
|
|
85
|
+
|
|
86
|
+
export const config: RouteConfig = {
|
|
87
|
+
label: "Reviews",
|
|
88
|
+
icon: Star,
|
|
89
|
+
rank: 10,
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export default function ReviewsPage() {
|
|
93
|
+
return <div>Reviews</div>
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
</Step>
|
|
97
|
+
<Step title="Add the config export for navigation">
|
|
98
|
+
A sidebar item is generated only when the page exports a `config` with a `label`. Pages without one are still routed — they just don't appear in the menu.
|
|
99
|
+
|
|
100
|
+
| Property | Type | Description |
|
|
101
|
+
|----------|------|-------------|
|
|
102
|
+
| `label` | `string` | **Required.** Text shown in the sidebar menu |
|
|
103
|
+
| `icon` | `ComponentType` | Icon component (e.g. from `@medusajs/icons`) |
|
|
104
|
+
| `rank` | `number` | Sort order — lower numbers appear first |
|
|
105
|
+
| `nested` | `string` | Parent path for nested menu items |
|
|
106
|
+
| `translationNs` | `string` | i18n namespace for the label |
|
|
107
|
+
| `public` | `boolean` | If `true`, the route is accessible without authentication |
|
|
108
|
+
|
|
109
|
+
Route files may also export a `loader` (React Router data loader) and `handle` (route metadata) alongside the default component.
|
|
110
|
+
</Step>
|
|
111
|
+
<Step title="Open it in the running panel">
|
|
112
|
+
Start the dev server — the SDK picks the file up automatically. This example creates a `/reviews` route with a "Reviews" sidebar item. No route registration, no configuration file.
|
|
113
|
+
</Step>
|
|
114
|
+
</Steps>
|
|
115
|
+
|
|
116
|
+
<Info>
|
|
117
|
+
**Matching paths replace, new paths append.** If your route's path matches a built-in page (e.g. `src/routes/products/page.tsx` → `/products`), your page **replaces** the built-in one — that's the override mechanism, no registration needed. Any other path is added alongside the built-in routes. Delete the file and the built-in page returns.
|
|
118
|
+
</Info>
|
|
119
|
+
|
|
120
|
+
### Routing conventions
|
|
121
|
+
|
|
122
|
+
File paths map to URL routes automatically:
|
|
123
|
+
|
|
124
|
+
| File path | Route | Description |
|
|
125
|
+
|-----------|-------|-------------|
|
|
126
|
+
| `src/routes/page.tsx` | `/` | Root page |
|
|
127
|
+
| `src/routes/reviews/page.tsx` | `/reviews` | Static segment |
|
|
128
|
+
| `src/routes/reviews/[id]/page.tsx` | `/reviews/:id` | Dynamic segment |
|
|
129
|
+
| `src/routes/reviews/[[id]]/page.tsx` | `/reviews/:id?` | Optional dynamic segment |
|
|
130
|
+
| `src/routes/search/[*]/page.tsx` | `/search/*` | Catch-all |
|
|
131
|
+
| `src/routes/(settings)/page.tsx` | Route grouping | Groups routes without adding a URL segment |
|
|
132
|
+
| `src/routes/dashboard/@sidebar/page.tsx` | Parallel route | Renders alongside parent |
|
|
133
|
+
|
|
134
|
+
## Navigation
|
|
135
|
+
|
|
136
|
+
Sidebar items are generated from pages that export a `config` with a `label`.
|
|
137
|
+
|
|
138
|
+
### Ordering
|
|
139
|
+
|
|
140
|
+
Use `rank` to control the order. Lower values appear higher:
|
|
141
|
+
|
|
142
|
+
```tsx
|
|
143
|
+
// src/routes/orders/page.tsx
|
|
144
|
+
export const config: RouteConfig = {
|
|
145
|
+
label: "Orders",
|
|
146
|
+
icon: ShoppingCart,
|
|
147
|
+
rank: 1,
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// src/routes/products/page.tsx
|
|
151
|
+
export const config: RouteConfig = {
|
|
152
|
+
label: "Products",
|
|
153
|
+
icon: Tag,
|
|
154
|
+
rank: 2,
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Nested menus
|
|
159
|
+
|
|
160
|
+
Use `nested` to group pages under a parent:
|
|
161
|
+
|
|
162
|
+
```tsx src/routes/settings/shipping/page.tsx
|
|
163
|
+
export const config: RouteConfig = {
|
|
164
|
+
label: "Shipping",
|
|
165
|
+
nested: "/settings",
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
This places "Shipping" as a child item under `/settings` in the sidebar.
|
|
170
|
+
|
|
171
|
+
## Branding
|
|
172
|
+
|
|
173
|
+
Set `name` and `logo` in the plugin options to customize the sidebar header:
|
|
174
|
+
|
|
175
|
+
```typescript vite.config.ts
|
|
176
|
+
mercurDashboardPlugin({
|
|
177
|
+
medusaConfigPath: '../../packages/api/medusa-config.ts',
|
|
178
|
+
name: 'WeTest',
|
|
179
|
+
logo: 'https://ui-avatars.com/api/?name=WeTest&background=18181B&color=fff&size=200&bold=true&format=svg',
|
|
180
|
+
})
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## Replace components
|
|
184
|
+
|
|
185
|
+
<Steps>
|
|
186
|
+
<Step title="Write the replacement">
|
|
187
|
+
Create the component anywhere under `src/`. It must have a default export:
|
|
188
|
+
|
|
189
|
+
```tsx src/components/custom-topbar-actions.tsx
|
|
190
|
+
export default function CustomTopbarActions() {
|
|
191
|
+
return (
|
|
192
|
+
<div>
|
|
193
|
+
<button>Help</button>
|
|
194
|
+
<button>Notifications</button>
|
|
195
|
+
</div>
|
|
196
|
+
)
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
</Step>
|
|
200
|
+
<Step title="Point the config at it">
|
|
201
|
+
Register it in the `components` option. Paths are relative to `src/`:
|
|
202
|
+
|
|
203
|
+
```typescript vite.config.ts
|
|
204
|
+
mercurDashboardPlugin({
|
|
205
|
+
medusaConfigPath: '../../packages/api/medusa-config.ts',
|
|
206
|
+
name: 'My Marketplace',
|
|
207
|
+
components: {
|
|
208
|
+
MainSidebar: 'components/custom-sidebar',
|
|
209
|
+
SettingsSidebar: 'components/custom-settings-sidebar',
|
|
210
|
+
TopbarActions: 'components/custom-topbar-actions',
|
|
211
|
+
},
|
|
212
|
+
})
|
|
213
|
+
```
|
|
214
|
+
</Step>
|
|
215
|
+
<Step title="Restart and verify">
|
|
216
|
+
Restart the dev server — your component now renders everywhere its slot appears. Remove the entry and restart to get the built-in back; the originals are never modified.
|
|
217
|
+
</Step>
|
|
218
|
+
</Steps>
|
|
219
|
+
|
|
220
|
+
| Component | Description |
|
|
221
|
+
|-----------|-------------|
|
|
222
|
+
| `MainSidebar` | Primary navigation sidebar |
|
|
223
|
+
| `SettingsSidebar` | Settings section sidebar |
|
|
224
|
+
| `TopbarActions` | Action buttons in the top bar |
|
|
225
|
+
| `StoreSetup` | Store setup screen for new sellers (vendor portal) |
|
|
226
|
+
|
|
227
|
+
<Warning>
|
|
228
|
+
These four slots are the complete list — there is no generic "replace any component" registry. If what you want to change isn't one of them, it's a page concern: [re-compose the page](/rc/resources/tutorials/recompose-a-page) instead.
|
|
229
|
+
</Warning>
|
|
230
|
+
|
|
231
|
+
## Internationalization
|
|
232
|
+
|
|
233
|
+
<Steps>
|
|
234
|
+
<Step title="Create translation resources">
|
|
235
|
+
```typescript src/i18n/index.ts
|
|
236
|
+
export default {
|
|
237
|
+
en: {
|
|
238
|
+
reviews: {
|
|
239
|
+
title: "Reviews",
|
|
240
|
+
description: "Manage product reviews",
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
de: {
|
|
244
|
+
reviews: {
|
|
245
|
+
title: "Bewertungen",
|
|
246
|
+
description: "Produktbewertungen verwalten",
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
</Step>
|
|
252
|
+
<Step title="Reference the namespace in your page config">
|
|
253
|
+
```tsx src/routes/reviews/page.tsx
|
|
254
|
+
export const config: RouteConfig = {
|
|
255
|
+
label: "reviews.title",
|
|
256
|
+
icon: Star,
|
|
257
|
+
translationNs: "reviews",
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
</Step>
|
|
261
|
+
<Step title="Set the default language">
|
|
262
|
+
```typescript vite.config.ts
|
|
263
|
+
mercurDashboardPlugin({
|
|
264
|
+
medusaConfigPath: '../../packages/api/medusa-config.ts',
|
|
265
|
+
name: 'My Marketplace',
|
|
266
|
+
i18n: {
|
|
267
|
+
defaultLanguage: 'en',
|
|
268
|
+
},
|
|
269
|
+
})
|
|
270
|
+
```
|
|
271
|
+
</Step>
|
|
272
|
+
</Steps>
|
|
273
|
+
|
|
274
|
+
## FAQ
|
|
275
|
+
|
|
276
|
+
<AccordionGroup>
|
|
277
|
+
<Accordion title="Can I use Medusa's defineWidgetConfig or widget zones?">
|
|
278
|
+
No. The Mercur panels don't load Medusa's admin extension system — there are no widget zones to inject into. The equivalent workflows are: drop-in routes for new pages, [compound-component re-composition](/rc/resources/tutorials/recompose-a-page) for changing existing pages, and the four `components` overrides for global chrome. Backend customization (workflows, modules, subscribers) still follows standard Medusa conventions.
|
|
279
|
+
</Accordion>
|
|
280
|
+
<Accordion title="How do I change just one part of a built-in page?">
|
|
281
|
+
Import the page from the `/pages` subpath (`@mercurjs/vendor/pages` or `@mercurjs/admin/pages`), drop a route at the same path, and re-compose its slots — keep the slots you don't change and they retain all their behavior (data fetching, filters, pagination). The [re-compose tutorial](/rc/resources/tutorials/recompose-a-page) walks through a real example.
|
|
282
|
+
</Accordion>
|
|
283
|
+
<Accordion title="Why doesn't my page show up in the sidebar?">
|
|
284
|
+
A sidebar item is only generated when the route file exports a `config` object with a `label`. Also check that the file is named exactly `page.tsx` (or `.ts`/`.jsx`/`.js`) under `src/routes/` and has a **default** export — files without one are skipped entirely.
|
|
285
|
+
</Accordion>
|
|
286
|
+
<Accordion title="Is there a mercur.config.ts file?">
|
|
287
|
+
No — all panel configuration is passed inline to `mercurDashboardPlugin()` in `vite.config.ts`. If you've seen references to a separate config file, they're outdated.
|
|
288
|
+
</Accordion>
|
|
289
|
+
<Accordion title="Does this apply to both the admin panel and the vendor portal?">
|
|
290
|
+
Yes — both panels use the same SDK and the same conventions. The differences are which built-in pages exist (`@mercurjs/admin/pages` vs `@mercurjs/vendor/pages`) and a few vendor-only options like `StoreSetup` and `enableSellerRegistration`.
|
|
291
|
+
</Accordion>
|
|
292
|
+
</AccordionGroup>
|
|
293
|
+
|
|
294
|
+
## Next steps
|
|
295
|
+
|
|
296
|
+
<CardGroup cols={2}>
|
|
297
|
+
<Card title="Add a custom panel page" href="/rc/resources/tutorials/custom-panel-page">
|
|
298
|
+
Hands-on: your first drop-in route, end to end.
|
|
299
|
+
</Card>
|
|
300
|
+
<Card title="Re-compose a built-in page" href="/rc/resources/tutorials/recompose-a-page">
|
|
301
|
+
Hands-on: override the vendor products page while keeping its table.
|
|
302
|
+
</Card>
|
|
303
|
+
<Card title="Replace panel components" href="/rc/resources/tutorials/replace-panel-components">
|
|
304
|
+
Hands-on: swap the topbar actions and sidebar.
|
|
305
|
+
</Card>
|
|
306
|
+
<Card title="Build your own block" href="/rc/resources/tutorials/build-a-block">
|
|
307
|
+
Package your customization and share it across projects.
|
|
308
|
+
</Card>
|
|
309
|
+
</CardGroup>
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Medusa Cloud deployment"
|
|
3
|
+
description: "Deploy Mercur — backend, admin panel, and vendor panel — on Medusa Cloud."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Introduction
|
|
7
|
+
|
|
8
|
+
[Medusa Cloud](https://cloud.medusajs.com) is a dedicated hosting service for Medusa-based applications. It automatically detects changes on your repository, pulls and builds the code, and provisions a database, Redis, and file storage.
|
|
9
|
+
|
|
10
|
+
Head to the [Medusa Cloud signup page](https://cloud.medusajs.com/signup) to get started. After registration is complete and your account is active, authorize the Medusa Cloud GitHub app in your organization or personal account.
|
|
11
|
+
|
|
12
|
+
<Info>
|
|
13
|
+
A single Medusa Cloud deployment serves everything: the backend API, the
|
|
14
|
+
**admin panel** at `/dashboard`, and the **vendor panel** at `/seller`. The
|
|
15
|
+
panels are built together with the backend and served from the same origin —
|
|
16
|
+
no separate hosting is needed.
|
|
17
|
+
</Info>
|
|
18
|
+
|
|
19
|
+
## How it works
|
|
20
|
+
|
|
21
|
+
The `basic` template wires this up out of the box:
|
|
22
|
+
|
|
23
|
+
- During `build`, the API package builds both panels and bundles their production
|
|
24
|
+
output into the Medusa build artifact (`.medusa/server/dashboards/<name>`), so hosts
|
|
25
|
+
that deploy only the artifact — like Medusa Cloud — carry the panels with it
|
|
26
|
+
(`packages/api/scripts/bundle-dashboards.mjs`).
|
|
27
|
+
- At runtime, the `admin-ui` and `vendor-ui` modules detect the bundled builds and
|
|
28
|
+
serve them statically at their configured paths (`/dashboard`, `/seller`).
|
|
29
|
+
- The panels bake the backend URL at build time from the `MERCUR_BACKEND_URL`
|
|
30
|
+
environment variable. Because they are served from the backend's own origin, all
|
|
31
|
+
API calls are same-origin — no cross-site cookie or CORS gymnastics.
|
|
32
|
+
|
|
33
|
+
Medusa Cloud builds the monorepo with `NODE_ENV=production`. In that mode the build
|
|
34
|
+
**fails fast** when `MERCUR_BACKEND_URL` is missing instead of shipping panels that
|
|
35
|
+
silently point at `http://localhost:9000` — so make sure to set it as described below.
|
|
36
|
+
|
|
37
|
+
## Prerequisites
|
|
38
|
+
|
|
39
|
+
- A Mercur project created with [`@mercurjs/cli`](/rc/learn/installation) and pushed to a GitHub repository
|
|
40
|
+
- A [Medusa Cloud](https://cloud.medusajs.com) account with the GitHub app authorized
|
|
41
|
+
- API keys for any third-party services you plan to use (Stripe, Resend, Algolia, etc.)
|
|
42
|
+
|
|
43
|
+
## Setup
|
|
44
|
+
|
|
45
|
+
<Steps>
|
|
46
|
+
<Step title="Import your repository">
|
|
47
|
+
From the Medusa Cloud dashboard, choose **Import your existing repository into the Cloud** (the Mercur project lives in your own GitHub repo, not in the bundled DTC/B2B starters).
|
|
48
|
+

|
|
49
|
+
</Step>
|
|
50
|
+
<Step title="Pick the repository">
|
|
51
|
+
On the **Repository** step, make sure the Medusa Cloud GitHub app is installed, pick your Mercur repository from the list, and click **Continue**.
|
|
52
|
+

|
|
53
|
+
</Step>
|
|
54
|
+
<Step title="Configure the project">
|
|
55
|
+
On the **Configure** step, fill in:
|
|
56
|
+
|
|
57
|
+
- **Project name** and **Custom subdomain**. The subdomain determines your backend URL (`https://<subdomain>.medusajs.app`) — you will reference it in the environment variables below.
|
|
58
|
+
- **Region** closest to your users.
|
|
59
|
+
- **Medusa root directory**: `/packages/api`.
|
|
60
|
+
- **Initial user** — the first admin email and password.
|
|
61
|
+
|
|
62
|
+
Leave **Storefront root directory** empty — the Mercur basic template doesn't ship a storefront.
|
|
63
|
+

|
|
64
|
+
</Step>
|
|
65
|
+
<Step title="Set environment variables">
|
|
66
|
+
Scroll down to **Environment variables** and add the **Backend Environment Variables** below. Medusa Cloud provisions the database, Redis, and file storage automatically, so you don't need to set those.
|
|
67
|
+

|
|
68
|
+
|
|
69
|
+
Only the following variables should be set:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
# Panels (build-time): the deployed backend origin, baked into the admin and
|
|
73
|
+
# vendor panels. Enable the **Build** toggle for this variable — the panels
|
|
74
|
+
# read it while they are being built, not at runtime.
|
|
75
|
+
MERCUR_BACKEND_URL=https://<your-subdomain>.medusajs.app
|
|
76
|
+
|
|
77
|
+
# CORS — the panels are served from the backend's own origin, so it is enough
|
|
78
|
+
# to list that origin (plus your storefront URL in STORE_CORS, if you have one)
|
|
79
|
+
STORE_CORS=https://<your-subdomain>.medusajs.app
|
|
80
|
+
ADMIN_CORS=https://<your-subdomain>.medusajs.app
|
|
81
|
+
VENDOR_CORS=https://<your-subdomain>.medusajs.app
|
|
82
|
+
AUTH_CORS=https://<your-subdomain>.medusajs.app
|
|
83
|
+
|
|
84
|
+
# Secrets
|
|
85
|
+
JWT_SECRET=
|
|
86
|
+
COOKIE_SECRET=
|
|
87
|
+
|
|
88
|
+
# Vendor panel URL used in seller emails and onboarding flows
|
|
89
|
+
MERCUR_VENDOR_URL=https://<your-subdomain>.medusajs.app/seller
|
|
90
|
+
|
|
91
|
+
# Stripe (customer payments + Mercur payout provider)
|
|
92
|
+
STRIPE_API_KEY=
|
|
93
|
+
STRIPE_WEBHOOK_SECRET=
|
|
94
|
+
STRIPE_PAYOUT_WEBHOOK_SECRET=
|
|
95
|
+
|
|
96
|
+
# Email (optional, e.g. Resend)
|
|
97
|
+
RESEND_API_KEY=
|
|
98
|
+
RESEND_FROM_EMAIL=
|
|
99
|
+
|
|
100
|
+
# Search (optional)
|
|
101
|
+
ALGOLIA_APP_ID=
|
|
102
|
+
ALGOLIA_API_KEY=
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
<Warning>
|
|
106
|
+
`MERCUR_BACKEND_URL` must have the **Build** toggle enabled in the Medusa Cloud
|
|
107
|
+
environment-variable settings. Without it, the production build stops with a clear
|
|
108
|
+
error rather than baking the localhost default into the panels.
|
|
109
|
+
</Warning>
|
|
110
|
+
|
|
111
|
+
<Info>
|
|
112
|
+
For Stripe setup, including which keys go where and how to wire both webhooks,
|
|
113
|
+
see the [Stripe Connect integration
|
|
114
|
+
guide](/rc/resources/integrations/stripe-connect).
|
|
115
|
+
</Info>
|
|
116
|
+
</Step>
|
|
117
|
+
<Step title="Create and deploy">
|
|
118
|
+
Click **Create**. The build and deploy process will start and can take a few minutes to complete.
|
|
119
|
+
</Step>
|
|
120
|
+
</Steps>
|
|
121
|
+
|
|
122
|
+
You can change these variables later from the project's environment settings, and switch the deployment branch at any time. Medusa Cloud will automatically pull and rebuild your environment whenever a new commit is pushed to the selected branch. Remember that `MERCUR_BACKEND_URL` is baked into the panels at build time — changing it requires a redeploy.
|
|
123
|
+
|
|
124
|
+
## After deployment
|
|
125
|
+
|
|
126
|
+
Once the build succeeds, everything is served from `https://<your-subdomain>.medusajs.app`:
|
|
127
|
+
|
|
128
|
+
| Surface | URL |
|
|
129
|
+
| ------------ | ------------------------------------------------ |
|
|
130
|
+
| Backend API | `https://<your-subdomain>.medusajs.app` |
|
|
131
|
+
| Admin panel | `https://<your-subdomain>.medusajs.app/dashboard` |
|
|
132
|
+
| Vendor panel | `https://<your-subdomain>.medusajs.app/seller` |
|
|
133
|
+
|
|
134
|
+
Open the admin panel and sign in with the **Initial user** you configured in the setup step. If a panel shows a "Dashboard not built" page, the bundling step did not run — check the deployment's build logs for output from `bundle-dashboards`.
|
|
135
|
+
|
|
136
|
+
<Tip>
|
|
137
|
+
Prefer hosting the panels separately (for example on Vercel or Netlify)? That
|
|
138
|
+
still works: deploy `apps/admin` and `apps/vendor` as static Vite builds, set
|
|
139
|
+
`MERCUR_BACKEND_URL` (or `VITE_MERCUR_BACKEND_URL`) to the backend URL at build
|
|
140
|
+
time, and add the panel URLs to the backend's `ADMIN_CORS`, `VENDOR_CORS`, and
|
|
141
|
+
`AUTH_CORS` variables.
|
|
142
|
+
</Tip>
|
|
143
|
+
|
|
144
|
+
## FAQ
|
|
145
|
+
|
|
146
|
+
<AccordionGroup>
|
|
147
|
+
<Accordion title="A panel shows a 'Dashboard not built' page — what went wrong?">
|
|
148
|
+
The bundling step didn't run during the build. Check the deployment's build logs for output from `bundle-dashboards`; the most common cause is a build that failed earlier (often a missing `MERCUR_BACKEND_URL` with the Build toggle off).
|
|
149
|
+
</Accordion>
|
|
150
|
+
<Accordion title="I changed MERCUR_BACKEND_URL but the panels still call the old URL">
|
|
151
|
+
The backend URL is **baked into the panels at build time**, not read at runtime. After changing the variable, trigger a redeploy so the panels rebuild with the new value.
|
|
152
|
+
</Accordion>
|
|
153
|
+
<Accordion title="Do I need to configure a database or Redis?">
|
|
154
|
+
No — Medusa Cloud provisions Postgres, Redis, and file storage automatically and injects their connection variables. Only set the variables listed in the setup step.
|
|
155
|
+
</Accordion>
|
|
156
|
+
</AccordionGroup>
|
|
157
|
+
|
|
158
|
+
## Next steps
|
|
159
|
+
|
|
160
|
+
<CardGroup cols={2}>
|
|
161
|
+
<Card title="Stripe Connect" href="/rc/resources/integrations/stripe-connect">
|
|
162
|
+
Wire payments and payouts on the deployed environment.
|
|
163
|
+
</Card>
|
|
164
|
+
<Card title="Build your first marketplace" href="/rc/resources/tutorials/first-marketplace">
|
|
165
|
+
Run the end-to-end flow against your new deployment.
|
|
166
|
+
</Card>
|
|
167
|
+
</CardGroup>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Notifications"
|
|
3
|
+
description: "Send transactional emails and marketplace notifications with Resend."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<Note>
|
|
7
|
+
This guide is being written. The outline below is the intended structure.
|
|
8
|
+
</Note>
|
|
9
|
+
|
|
10
|
+
<Info>
|
|
11
|
+
**Two notification surfaces.** Mercur sends provider-backed transactional email (seller approvals, invites, order events) *and* keeps an in-app vendor notification feed in the Vendor Portal. The email side uses Medusa's standard notification-provider model — Resend is the documented default, but any Medusa notification provider plugs in the same way.
|
|
12
|
+
</Info>
|
|
13
|
+
|
|
14
|
+
## What Resend powers
|
|
15
|
+
|
|
16
|
+
The emails and notifications Mercur sends, and where they're triggered.
|
|
17
|
+
|
|
18
|
+
<Steps>
|
|
19
|
+
<Step title="Prerequisites">
|
|
20
|
+
Resend account, API key, and environment variables.
|
|
21
|
+
</Step>
|
|
22
|
+
<Step title="Configure the provider">
|
|
23
|
+
Wire Resend as the notification provider.
|
|
24
|
+
</Step>
|
|
25
|
+
<Step title="Send a test notification">
|
|
26
|
+
Trigger a test notification and confirm delivery.
|
|
27
|
+
</Step>
|
|
28
|
+
</Steps>
|
|
29
|
+
|
|
30
|
+
## Verify
|
|
31
|
+
|
|
32
|
+
Trigger a test notification and confirm delivery.
|
|
33
|
+
|
|
34
|
+
## Next steps
|
|
35
|
+
|
|
36
|
+
<CardGroup cols={2}>
|
|
37
|
+
<Card title="Search" href="/rc/resources/integrations/search" />
|
|
38
|
+
<Card title="Deploy to Medusa Cloud" href="/rc/resources/deployment/medusa-cloud" />
|
|
39
|
+
</CardGroup>
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Search"
|
|
3
|
+
description: "Mercur's provider-agnostic search module — zero-infrastructure Orama by default, swappable for Algolia, Meilisearch, or your own provider."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Mercur ships a **Search module** in `@mercurjs/core`, modeled on Medusa's pluggable-provider pattern (like the `file` and `notification` modules). The module owns a stable contract — `index`, `remove`, `search` — and delegates storage to exactly one active **provider**. Out of the box that provider is [Orama](https://docs.orama.com): an in-process, in-memory index that needs zero external infrastructure.
|
|
7
|
+
|
|
8
|
+
<Warning>
|
|
9
|
+
The search module is a release-candidate feature and its surface may still evolve before the stable release.
|
|
10
|
+
</Warning>
|
|
11
|
+
|
|
12
|
+
<Info>
|
|
13
|
+
**Everything above the provider is provider-agnostic.** Subscribers index and remove documents on product, offer, and seller events; the store route calls `search.search(query)`; boot reindexing is event-driven. Swapping Orama for Algolia or Meilisearch means changing one provider registration — no changes to subscribers, the store route, or your storefront.
|
|
14
|
+
</Info>
|
|
15
|
+
|
|
16
|
+
## What gets indexed
|
|
17
|
+
|
|
18
|
+
Products **and offers** are searchable. Offers are indexed as **per-offer documents** — one hit per vendor listing — each carrying the offer's scoped price, so search results price identically to `GET /store/offers`. Index updates are driven by subscribers on product, offer, and seller events; you never call `index()` from application code.
|
|
19
|
+
|
|
20
|
+
## Searching from the storefront
|
|
21
|
+
|
|
22
|
+
The Store API exposes one endpoint:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
curl -X POST "http://localhost:9000/store/search" \
|
|
26
|
+
-H "x-publishable-api-key: <key>" \
|
|
27
|
+
-H "Content-Type: application/json" \
|
|
28
|
+
-d '{
|
|
29
|
+
"q": "t-shirt",
|
|
30
|
+
"limit": 12,
|
|
31
|
+
"offset": 0,
|
|
32
|
+
"region_id": "reg_123"
|
|
33
|
+
}'
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
| Field | Description |
|
|
37
|
+
|-------|-------------|
|
|
38
|
+
| `q` | Search query (defaults to `""` — browse mode) |
|
|
39
|
+
| `limit` / `offset` | Pagination (limit 1–100, default 12) |
|
|
40
|
+
| `region_id`, `country_code`, `province` | Pricing context — the provider projects the matching price onto each hit's `calculated_price` |
|
|
41
|
+
| `filters` | Passed straight to the active provider, which owns its shape |
|
|
42
|
+
|
|
43
|
+
The response returns `hits`, `count`, and `facets`.
|
|
44
|
+
|
|
45
|
+
## The default provider: Orama
|
|
46
|
+
|
|
47
|
+
The bundled `search-orama` provider keeps the index in RAM inside the API process. That means:
|
|
48
|
+
|
|
49
|
+
- **Zero setup** — no accounts, keys, or services. Search works on a fresh project.
|
|
50
|
+
- **Boot reindex** — an in-memory index is empty after a restart, so the module emits a reindex event on application start and a subscriber rebuilds the index from the database.
|
|
51
|
+
|
|
52
|
+
<Note>
|
|
53
|
+
In-memory search fits development and small-to-medium catalogs. For large catalogs or multi-instance deployments, use a persistent provider — the index then lives in the external service and the boot reindex is unnecessary.
|
|
54
|
+
</Note>
|
|
55
|
+
|
|
56
|
+
## Swapping in Algolia or Meilisearch
|
|
57
|
+
|
|
58
|
+
Ready-made provider integrations ship as blocks:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
bunx @mercurjs/cli@rc add algolia
|
|
62
|
+
# or
|
|
63
|
+
bunx @mercurjs/cli@rc add meilisearch
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
| Provider | Hosting | Best for |
|
|
67
|
+
|----------|---------|----------|
|
|
68
|
+
| Orama (default) | In-process | Zero-infra development and smaller catalogs |
|
|
69
|
+
| Algolia | Managed SaaS | Fastest setup, hosted relevance tuning |
|
|
70
|
+
| Meilisearch | Self-hosted or cloud | Full control, open source |
|
|
71
|
+
|
|
72
|
+
Each block installs the provider source and prints the configuration steps (API keys, module options). Follow the block's post-install docs to register the provider and set environment variables.
|
|
73
|
+
|
|
74
|
+
## Writing your own provider
|
|
75
|
+
|
|
76
|
+
A provider extends `AbstractSearchProvider` from `@mercurjs/core` and implements three methods:
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
import { AbstractSearchProvider } from "@mercurjs/core/modules/search"
|
|
80
|
+
import { SearchDoc, SearchQueryBase, SearchResults } from "@mercurjs/types"
|
|
81
|
+
|
|
82
|
+
export class MySearchProvider extends AbstractSearchProvider {
|
|
83
|
+
static identifier = "my-search"
|
|
84
|
+
|
|
85
|
+
async index(docs: SearchDoc[]): Promise<void> { /* upsert documents */ }
|
|
86
|
+
async remove(ids: string[]): Promise<void> { /* delete by id */ }
|
|
87
|
+
async search(query: SearchQueryBase): Promise<SearchResults> { /* query + facets */ }
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Because subscribers and the store route only talk to the module contract, your provider slots in without touching anything else. Use the Algolia or Meilisearch block source as a working reference.
|
|
92
|
+
|
|
93
|
+
## Verify
|
|
94
|
+
|
|
95
|
+
1. Start a fresh project and `POST /store/search` with an empty `q` — published products return without any search service configured (that's Orama).
|
|
96
|
+
2. Publish a product and search for its title — it appears without a manual reindex (subscribers indexed it).
|
|
97
|
+
3. Restart the API and search again — results still return (the boot reindex rebuilt the in-memory index).
|
|
98
|
+
|
|
99
|
+
## FAQ
|
|
100
|
+
|
|
101
|
+
<AccordionGroup>
|
|
102
|
+
<Accordion title="Can I run two providers at once, e.g. Orama locally and Algolia in production?">
|
|
103
|
+
Only one provider is active at a time — the module has no multi-provider machinery. But because the provider is chosen by configuration, you can register different providers per environment (default Orama in development, Algolia in production) without touching any other code.
|
|
104
|
+
</Accordion>
|
|
105
|
+
<Accordion title="Do I ever need to trigger a reindex manually?">
|
|
106
|
+
Normally no — subscribers keep the index current, and in-memory providers rebuild on boot. A manual full reindex is only interesting after bulk data changes outside normal flows (e.g. direct DB imports); persistent providers ignore the boot event entirely.
|
|
107
|
+
</Accordion>
|
|
108
|
+
<Accordion title="Why does each offer appear as its own search hit?">
|
|
109
|
+
Because pricing and availability are per offer, not per product. One hit per vendor listing lets results carry the correct `calculated_price` for each seller — the same numbers as `GET /store/offers` — instead of an ambiguous product-level price.
|
|
110
|
+
</Accordion>
|
|
111
|
+
</AccordionGroup>
|
|
112
|
+
|
|
113
|
+
## Next steps
|
|
114
|
+
|
|
115
|
+
<CardGroup cols={2}>
|
|
116
|
+
<Card title="Offers" href="/rc/learn/offers">
|
|
117
|
+
Why offers are indexed per seller with scoped prices.
|
|
118
|
+
</Card>
|
|
119
|
+
<Card title="Add a feature with a block" href="/rc/resources/tutorials/add-a-block">
|
|
120
|
+
How provider blocks are installed and configured.
|
|
121
|
+
</Card>
|
|
122
|
+
</CardGroup>
|