@mercurjs/docs 2.2.1 → 2.3.0-canary.1
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/content/home.mdx +107 -0
- package/content/learn/architecture.mdx +168 -83
- package/content/learn/introduction.mdx +161 -56
- package/content/learn/migration-to-2-0.mdx +187 -0
- package/content/learn/why-mercur.mdx +91 -0
- package/content/platform/attribute/concepts/attribute-types.mdx +59 -0
- package/content/platform/attribute/concepts/global-vs-inline.mdx +50 -0
- package/content/platform/attribute/concepts/variant-axes.mdx +61 -0
- package/content/platform/attribute/guides/attach-attributes-to-a-product.mdx +69 -0
- package/content/platform/attribute/guides/create-a-variant-axis.mdx +83 -0
- package/content/platform/attribute/guides/create-an-attribute.mdx +81 -0
- package/content/platform/attribute/overview.mdx +87 -0
- package/content/platform/attribute/reference/data-models.mdx +56 -0
- package/content/platform/attribute/reference/events.mdx +41 -0
- package/content/platform/attribute/reference/links.mdx +45 -0
- package/content/platform/attribute/reference/service.mdx +49 -0
- package/content/platform/attribute/reference/workflows.mdx +45 -0
- package/content/platform/catalog/concepts/master-products.mdx +54 -0
- package/content/platform/catalog/concepts/product-seller-allowlist.mdx +48 -0
- package/content/platform/catalog/concepts/status-lifecycle.mdx +58 -0
- package/content/platform/catalog/concepts/variants-categories-collections.mdx +49 -0
- package/content/platform/catalog/guides/allowlist-stores.mdx +59 -0
- package/content/platform/catalog/guides/create-a-master-product.mdx +70 -0
- package/content/platform/catalog/guides/publish-or-reject-a-product.mdx +79 -0
- package/content/platform/catalog/overview.mdx +90 -0
- package/content/platform/catalog/reference/data-models.mdx +66 -0
- package/content/platform/catalog/reference/events.mdx +41 -0
- package/content/platform/catalog/reference/links.mdx +44 -0
- package/content/platform/catalog/reference/service.mdx +52 -0
- package/content/platform/catalog/reference/workflows.mdx +40 -0
- package/content/platform/commission/concepts/order-commission-lines.mdx +65 -0
- package/content/platform/commission/concepts/rule-matching.mdx +86 -0
- package/content/platform/commission/concepts/rules-and-rates.mdx +84 -0
- package/content/platform/commission/guides/batch-update-rules.mdx +58 -0
- package/content/platform/commission/guides/create-a-rate.mdx +72 -0
- package/content/platform/commission/guides/refresh-order-commission-lines.mdx +55 -0
- package/content/platform/commission/overview.mdx +86 -0
- package/content/platform/commission/reference/data-models.mdx +75 -0
- package/content/platform/commission/reference/events.mdx +58 -0
- package/content/platform/commission/reference/links.mdx +45 -0
- package/content/platform/commission/reference/service.mdx +51 -0
- package/content/platform/commission/reference/workflows.mdx +40 -0
- package/content/platform/offer/concepts/pricing-and-inventory.mdx +72 -0
- package/content/platform/offer/concepts/shipping.mdx +48 -0
- package/content/platform/offer/concepts/what-is-an-offer.mdx +65 -0
- package/content/platform/offer/guides/bulk-create-offers.mdx +84 -0
- package/content/platform/offer/guides/create-an-offer.mdx +83 -0
- package/content/platform/offer/guides/manage-offer-inventory.mdx +53 -0
- package/content/platform/offer/overview.mdx +84 -0
- package/content/platform/offer/reference/data-models.mdx +56 -0
- package/content/platform/offer/reference/events.mdx +39 -0
- package/content/platform/offer/reference/links.mdx +60 -0
- package/content/platform/offer/reference/service.mdx +53 -0
- package/content/platform/offer/reference/workflows.mdx +38 -0
- package/content/platform/order-group/concepts/computed-totals.mdx +59 -0
- package/content/platform/order-group/concepts/order-splitting.mdx +61 -0
- package/content/platform/order-group/concepts/the-order-group.mdx +64 -0
- package/content/platform/order-group/guides/list-order-groups.mdx +67 -0
- package/content/platform/order-group/guides/retrieve-an-order-group.mdx +63 -0
- package/content/platform/order-group/guides/split-a-cart.mdx +58 -0
- package/content/platform/order-group/overview.mdx +83 -0
- package/content/platform/order-group/reference/data-models.mdx +40 -0
- package/content/platform/order-group/reference/events.mdx +37 -0
- package/content/platform/order-group/reference/links.mdx +45 -0
- package/content/platform/order-group/reference/service.mdx +50 -0
- package/content/platform/order-group/reference/workflows.mdx +39 -0
- package/content/platform/payout/concepts/account-lifecycle.mdx +75 -0
- package/content/platform/payout/concepts/accounts-and-onboarding.mdx +70 -0
- package/content/platform/payout/concepts/payout-pipeline.mdx +99 -0
- package/content/platform/payout/guides/create-a-payout-account.mdx +59 -0
- package/content/platform/payout/guides/process-a-provider-webhook.mdx +74 -0
- package/content/platform/payout/guides/start-provider-onboarding.mdx +50 -0
- package/content/platform/payout/overview.mdx +86 -0
- package/content/platform/payout/reference/data-models.mdx +61 -0
- package/content/platform/payout/reference/events.mdx +48 -0
- package/content/platform/payout/reference/links.mdx +36 -0
- package/content/platform/payout/reference/service.mdx +53 -0
- package/content/platform/payout/reference/workflows.mdx +32 -0
- package/content/platform/product-edit/concepts/change-actions.mdx +66 -0
- package/content/platform/product-edit/concepts/change-pipeline.mdx +69 -0
- package/content/platform/product-edit/concepts/status-and-auto-confirm.mdx +66 -0
- package/content/platform/product-edit/guides/confirm-or-decline-a-change.mdx +76 -0
- package/content/platform/product-edit/guides/edit-a-product.mdx +74 -0
- package/content/platform/product-edit/guides/request-a-revision.mdx +54 -0
- package/content/platform/product-edit/overview.mdx +85 -0
- package/content/platform/product-edit/reference/data-models.mdx +65 -0
- package/content/platform/product-edit/reference/events.mdx +47 -0
- package/content/platform/product-edit/reference/links.mdx +39 -0
- package/content/platform/product-edit/reference/service.mdx +43 -0
- package/content/platform/product-edit/reference/workflows.mdx +49 -0
- package/content/platform/review/concepts/product-vs-seller-reviews.mdx +63 -0
- package/content/platform/review/concepts/ratings-and-moderation.mdx +64 -0
- package/content/platform/review/concepts/the-review-model.mdx +56 -0
- package/content/platform/review/guides/compute-aggregate-ratings.mdx +57 -0
- package/content/platform/review/guides/create-a-review.mdx +55 -0
- package/content/platform/review/guides/moderate-a-review.mdx +58 -0
- package/content/platform/review/guides/respond-to-a-review.mdx +61 -0
- package/content/platform/review/overview.mdx +87 -0
- package/content/platform/review/reference/data-models.mdx +36 -0
- package/content/platform/review/reference/events.mdx +61 -0
- package/content/platform/review/reference/links.mdx +43 -0
- package/content/platform/review/reference/service.mdx +54 -0
- package/content/platform/review/reference/workflows.mdx +31 -0
- package/content/platform/store/concepts/lifecycle.mdx +62 -0
- package/content/platform/store/concepts/store-entity.mdx +53 -0
- package/content/platform/store/concepts/team.mdx +50 -0
- package/content/platform/store/guides/create-a-store.mdx +55 -0
- package/content/platform/store/guides/manage-the-team.mdx +55 -0
- package/content/platform/store/guides/moderate-a-store.mdx +59 -0
- package/content/platform/store/overview.mdx +86 -0
- package/content/platform/store/reference/data-models.mdx +89 -0
- package/content/platform/store/reference/events.mdx +43 -0
- package/content/platform/store/reference/links.mdx +71 -0
- package/content/platform/store/reference/service.mdx +51 -0
- package/content/platform/store/reference/workflows.mdx +35 -0
- package/content/references/api/admin/commission-rates/create-commission-rate.mdx +1 -1
- package/content/references/api/admin/commission-rates/list-commission-rates.mdx +2 -2
- package/content/references/api/admin/commission-rates/update-commission-rate.mdx +1 -1
- package/content/references/api/admin/offers/batch-create-offers.mdx +3 -3
- package/content/references/api/admin/order-groups/list-order-groups.mdx +1 -1
- package/content/references/api/admin/product-attributes/create-attribute-value.mdx +2 -2
- package/content/references/api/admin/product-attributes/create-product-attribute.mdx +1 -1
- package/content/references/api/admin/product-attributes/update-product-attribute.mdx +1 -1
- package/content/references/api/admin/product-changes/confirm-product-change.mdx +1 -1
- package/content/references/api/admin/products/batch-product-attributes.mdx +1 -1
- package/content/references/api/admin/products/create-product.mdx +1 -1
- package/content/references/api/admin/products/preview-product.mdx +1 -1
- package/content/references/api/admin.mdx +4 -5
- package/content/references/api/conventions.mdx +9 -7
- package/content/references/api/store/carts/add-line-item.mdx +1 -1
- package/content/references/api/store/offers/list-offers.mdx +1 -1
- package/content/references/api/store/order-groups/list-order-groups.mdx +1 -1
- package/content/references/api/store.mdx +4 -13
- package/content/references/api/vendor/members/accept-member-invite.mdx +1 -1
- package/content/references/api/vendor/offers/batch-create-offers.mdx +4 -0
- package/content/references/api/vendor/offers/batch-offer-inventory-items.mdx +2 -0
- package/content/references/api/vendor/offers/create-offer.mdx +13 -1
- package/content/references/api/vendor/offers/list-offers.mdx +4 -0
- package/content/references/api/vendor/offers/retrieve-offer.mdx +4 -0
- package/content/references/api/vendor/offers/update-offer.mdx +12 -0
- package/content/references/api/vendor/payout-accounts/create-onboarding.mdx +1 -1
- package/content/references/api/vendor/products/batch-product-attributes.mdx +1 -1
- package/content/references/api/vendor/products/create-product-variant.mdx +1 -1
- package/content/references/api/vendor/products/create-product.mdx +1 -1
- package/content/references/api/vendor/products/delete-product.mdx +1 -1
- package/content/references/api/vendor/products/update-product.mdx +1 -1
- package/content/references/api/vendor/sellers/create-seller.mdx +2 -2
- package/content/references/api/vendor/sellers/list-sellers.mdx +1 -1
- package/content/references/api/vendor.mdx +6 -5
- package/content/references/configuration.mdx +16 -33
- package/content/references/overview.mdx +34 -52
- package/content/references/panel-extensions/create-page.mdx +194 -0
- package/content/references/panel-extensions/custom-fields.mdx +256 -0
- package/content/references/panel-extensions/overview.mdx +102 -0
- package/content/references/panel-extensions/widgets.mdx +212 -0
- package/content/resources/ai/mcp.mdx +2 -2
- package/content/resources/ai/overview.mdx +21 -16
- package/content/resources/ai/skills.mdx +67 -0
- package/content/resources/best-practices/api-routes.mdx +55 -43
- package/content/resources/best-practices/custom-fields.mdx +116 -92
- package/content/resources/best-practices/frontend.mdx +62 -50
- package/content/resources/best-practices/module-links.mdx +48 -34
- package/content/resources/best-practices/modules.mdx +53 -27
- package/content/resources/best-practices/overview.mdx +45 -17
- package/content/resources/best-practices/subscribers-and-jobs.mdx +37 -24
- package/content/resources/best-practices/types.mdx +38 -23
- package/content/resources/best-practices/workflows.mdx +33 -21
- package/content/resources/customization/custom-fields.mdx +15 -15
- package/content/resources/customization/extend-a-workflow.mdx +7 -4
- package/content/resources/customization/extending-panels.mdx +55 -52
- package/content/resources/deployment/medusa-cloud.mdx +21 -20
- package/content/resources/deployment/self-host.mdx +123 -0
- package/content/resources/integrations/overview.mdx +38 -0
- package/content/resources/integrations/stripe-connect.mdx +39 -38
- package/content/resources/tutorials/add-a-block.mdx +25 -18
- package/content/resources/tutorials/add-a-widget.mdx +32 -23
- package/content/resources/tutorials/add-order-detail-button.mdx +33 -20
- package/content/resources/tutorials/attributes-and-variant-axes.mdx +28 -27
- package/content/resources/tutorials/build-a-block.mdx +26 -15
- package/content/resources/tutorials/custom-api-route.mdx +32 -20
- package/content/resources/tutorials/custom-panel-page.mdx +21 -12
- package/content/resources/tutorials/customize-navigation.mdx +30 -23
- package/content/resources/tutorials/extend-forms-and-tables.mdx +36 -28
- package/content/resources/tutorials/extend-onboarding.mdx +38 -35
- package/content/resources/tutorials/master-products-and-offers.mdx +28 -23
- package/content/telemetry.mdx +3 -3
- package/content/user-guide/admin/attributes/how-tos/create-an-attribute.mdx +64 -0
- package/content/user-guide/admin/attributes/how-tos/manage-possible-values.mdx +40 -0
- package/content/user-guide/admin/attributes/overview.mdx +22 -0
- package/content/user-guide/admin/commissions/how-tos/create-a-commission-rule.mdx +63 -0
- package/content/user-guide/admin/commissions/how-tos/edit-the-global-commission.mdx +48 -0
- package/content/user-guide/admin/commissions/how-tos/manage-a-commission-rule.mdx +45 -0
- package/content/user-guide/admin/commissions/overview.mdx +25 -0
- package/content/user-guide/admin/overview.mdx +20 -12
- package/content/user-guide/admin/product-requests/how-tos/review-a-new-product.mdx +58 -0
- package/content/user-guide/admin/product-requests/how-tos/review-a-product-edit.mdx +48 -0
- package/content/user-guide/admin/product-requests/overview.mdx +25 -0
- package/content/user-guide/vendor/offers/how-tos/create-an-offer.mdx +59 -0
- package/content/user-guide/vendor/offers/how-tos/update-prices-and-stock.mdx +40 -0
- package/content/user-guide/vendor/offers/overview.mdx +22 -0
- package/content/user-guide/vendor/onboarding.mdx +79 -0
- package/content/user-guide/vendor/orders/how-tos/fulfill-an-order.mdx +49 -0
- package/content/user-guide/vendor/orders/how-tos/mark-an-order-as-delivered.mdx +33 -0
- package/content/user-guide/vendor/orders/how-tos/process-a-return.mdx +42 -0
- package/content/user-guide/vendor/orders/how-tos/refund-an-order.mdx +38 -0
- package/content/user-guide/vendor/orders/how-tos/ship-an-order.mdx +40 -0
- package/content/user-guide/vendor/orders/overview.mdx +31 -0
- package/content/user-guide/vendor/overview.mdx +23 -12
- package/content/user-guide/vendor/products/how-tos/edit-a-product.mdx +44 -0
- package/content/user-guide/vendor/products/how-tos/submit-a-product.mdx +63 -0
- package/content/user-guide/vendor/products/overview.mdx +22 -0
- package/llms.txt +176 -142
- package/package.json +1 -1
- package/content/learn/concepts.mdx +0 -84
- package/content/learn/installation.mdx +0 -117
- package/content/learn/mirakl-alternative.mdx +0 -86
- package/content/migration/from-1-x-to-2-0.mdx +0 -152
- package/content/migration/from-2-0-to-2-1.mdx +0 -105
- package/content/migration/overview.mdx +0 -58
- package/content/references/api/store/search/search.mdx +0 -136
- package/content/references/modules/commission.mdx +0 -106
- package/content/references/modules/custom-fields.mdx +0 -45
- package/content/references/modules/media.mdx +0 -55
- package/content/references/modules/offer.mdx +0 -64
- package/content/references/modules/payout.mdx +0 -121
- package/content/references/modules/product-attribute.mdx +0 -111
- package/content/references/modules/product-edit.mdx +0 -80
- package/content/references/modules/search.mdx +0 -112
- package/content/references/modules/seller.mdx +0 -175
- package/content/references/panel-extension-api.mdx +0 -337
- package/content/references/workflows/cart/add-seller-shipping-method-to-cart.mdx +0 -48
- package/content/references/workflows/cart/complete-cart-with-split-orders.mdx +0 -36
- package/content/references/workflows/cart/list-seller-shipping-options-for-cart.mdx +0 -39
- package/content/references/workflows/cart/update-cart-seller-promotions.mdx +0 -42
- package/content/references/workflows/commission/batch-commission-rules.mdx +0 -49
- package/content/references/workflows/commission/create-commission-rates.mdx +0 -41
- package/content/references/workflows/commission/delete-commission-rates.mdx +0 -34
- package/content/references/workflows/commission/refresh-order-commission-lines.mdx +0 -30
- package/content/references/workflows/commission/update-commission-rates.mdx +0 -35
- package/content/references/workflows/media/set-category-images.mdx +0 -41
- package/content/references/workflows/media/set-collection-images.mdx +0 -41
- package/content/references/workflows/member/accept-member-invite.mdx +0 -33
- package/content/references/workflows/member/add-seller-member.mdx +0 -30
- package/content/references/workflows/member/create-member-invites.mdx +0 -34
- package/content/references/workflows/member/delete-member-invite.mdx +0 -24
- package/content/references/workflows/member/remove-seller-member.mdx +0 -28
- package/content/references/workflows/member/resend-member-invite.mdx +0 -28
- package/content/references/workflows/member/update-member-role.mdx +0 -28
- package/content/references/workflows/member/update-member.mdx +0 -35
- package/content/references/workflows/offer/batch-offer-inventory-items.mdx +0 -62
- package/content/references/workflows/offer/create-offers.mdx +0 -65
- package/content/references/workflows/offer/delete-offers.mdx +0 -35
- package/content/references/workflows/offer/update-offers.mdx +0 -53
- package/content/references/workflows/order/cancel-order-fulfillment.mdx +0 -34
- package/content/references/workflows/order/confirm-claim-request.mdx +0 -25
- package/content/references/workflows/order/confirm-exchange-request.mdx +0 -25
- package/content/references/workflows/order/confirm-order-edit-request.mdx +0 -25
- package/content/references/workflows/order/confirm-return-receive.mdx +0 -25
- package/content/references/workflows/order/create-order-fulfillment.mdx +0 -45
- package/content/references/workflows/order-group/get-order-group-detail.mdx +0 -29
- package/content/references/workflows/order-group/get-order-groups-list.mdx +0 -38
- package/content/references/workflows/overview.mdx +0 -72
- package/content/references/workflows/payout/create-onboarding.mdx +0 -36
- package/content/references/workflows/payout/create-payout-account.mdx +0 -33
- package/content/references/workflows/payout/create-payout.mdx +0 -30
- package/content/references/workflows/payout/process-payout-for-webhook.mdx +0 -34
- package/content/references/workflows/product/confirm-products.mdx +0 -48
- package/content/references/workflows/product/create-products.mdx +0 -63
- package/content/references/workflows/product/link-sellers-to-product-category.mdx +0 -40
- package/content/references/workflows/product/link-sellers-to-product.mdx +0 -40
- package/content/references/workflows/product/reject-product.mdx +0 -48
- package/content/references/workflows/product/request-product-change.mdx +0 -48
- package/content/references/workflows/product-attribute/add-product-attributes-to-product.mdx +0 -49
- package/content/references/workflows/product-attribute/create-and-link-product-attributes-to-product.mdx +0 -46
- package/content/references/workflows/product-attribute/create-product-attribute-values.mdx +0 -43
- package/content/references/workflows/product-attribute/create-product-attributes.mdx +0 -56
- package/content/references/workflows/product-attribute/delete-product-attribute-values.mdx +0 -30
- package/content/references/workflows/product-attribute/delete-product-attributes.mdx +0 -30
- package/content/references/workflows/product-attribute/remove-product-attributes-from-product.mdx +0 -29
- package/content/references/workflows/product-attribute/update-product-attribute-values.mdx +0 -44
- package/content/references/workflows/product-attribute/update-product-attributes-on-product.mdx +0 -41
- package/content/references/workflows/product-attribute/update-product-attributes.mdx +0 -48
- package/content/references/workflows/product-attribute/upsert-product-attribute-values.mdx +0 -43
- package/content/references/workflows/product-edit/auto-confirm-product-change.mdx +0 -39
- package/content/references/workflows/product-edit/cancel-product-change.mdx +0 -49
- package/content/references/workflows/product-edit/confirm-product-change.mdx +0 -57
- package/content/references/workflows/product-edit/create-product-change.mdx +0 -72
- package/content/references/workflows/product-edit/reject-product-change.mdx +0 -54
- package/content/references/workflows/product-edit/stage-product-change.mdx +0 -75
- package/content/references/workflows/seller/approve-seller.mdx +0 -36
- package/content/references/workflows/seller/create-seller-account.mdx +0 -59
- package/content/references/workflows/seller/create-seller-defaults.mdx +0 -22
- package/content/references/workflows/seller/create-sellers.mdx +0 -65
- package/content/references/workflows/seller/delete-seller-professional-details.mdx +0 -37
- package/content/references/workflows/seller/delete-sellers.mdx +0 -24
- package/content/references/workflows/seller/invite-seller.mdx +0 -28
- package/content/references/workflows/seller/suspend-seller.mdx +0 -37
- package/content/references/workflows/seller/terminate-seller.mdx +0 -37
- package/content/references/workflows/seller/unsuspend-seller.mdx +0 -36
- package/content/references/workflows/seller/unterminate-seller.mdx +0 -36
- package/content/references/workflows/seller/update-seller-address.mdx +0 -55
- package/content/references/workflows/seller/update-seller-payment-details.mdx +0 -52
- package/content/references/workflows/seller/update-seller-professional-details.mdx +0 -48
- package/content/references/workflows/seller/update-sellers.mdx +0 -57
- package/content/resources/ai/llms.mdx +0 -74
- package/content/resources/integrations/notifications.mdx +0 -39
- package/content/resources/integrations/search.mdx +0 -122
- package/content/resources/tutorials/configure-commissions.mdx +0 -127
- package/content/resources/tutorials/first-marketplace.mdx +0 -45
- package/content/resources/tutorials/handle-product-requests.mdx +0 -80
- package/content/resources/tutorials/import-export-products.mdx +0 -96
- package/content/resources/tutorials/seller-payouts-stripe.mdx +0 -89
- package/content/resources/tutorials/store-setup-checklist.mdx +0 -214
- package/content/tools/api-client.mdx +0 -155
- package/content/tools/cli.mdx +0 -196
- package/content/tools/dashboard-sdk.mdx +0 -35
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "
|
|
3
|
-
|
|
2
|
+
title: "How to Add an Action Button"
|
|
3
|
+
sidebarTitle: "Add an Action Button"
|
|
4
|
+
description: "Add a Copy link button to the vendor order detail page with a widget, without forking or overriding the page."
|
|
4
5
|
---
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
Add a small piece of UI to a built-in panel screen without copying it.
|
|
7
8
|
|
|
8
|
-
This tutorial adds a **
|
|
9
|
+
The order detail page is a panel screen you don't own. To add a button, a badge, or a note to it, you drop a **widget** at one of its zones. The SDK renders your component there, and the rest of the page keeps working exactly as shipped. This tutorial adds a **Copy link** button to the order summary section that copies a link to the order.
|
|
9
10
|
|
|
10
11
|
<Info>
|
|
11
|
-
|
|
12
|
+
A widget is additive, not a replacement. It layers your component onto a built-in page at a documented zone. Reach for it first whenever you just want to add something to an existing screen.
|
|
12
13
|
</Info>
|
|
13
14
|
|
|
14
15
|
## Add the button
|
|
15
16
|
|
|
16
17
|
<Steps>
|
|
17
18
|
<Step title="Create the widget file">
|
|
18
|
-
Drop a file under `src/widgets/`. Export the component as the **default** and a `config` built with `defineWidgetConfig`. Target `orders.detail.summary.after
|
|
19
|
+
Drop a file under `src/widgets/`. Export the component as the **default** and a `config` built with `defineWidgetConfig`. Target `orders.detail.summary.after`. Your component renders in the order summary section footer and receives the loaded order as `data`.
|
|
19
20
|
|
|
20
21
|
```tsx apps/vendor/src/widgets/order-copy-link.tsx
|
|
21
22
|
import { defineWidgetConfig } from "@mercurjs/dashboard-sdk"
|
|
@@ -52,24 +53,30 @@ This tutorial adds a **"Copy link"** button to the order summary section that co
|
|
|
52
53
|
export default OrderCopyLink
|
|
53
54
|
```
|
|
54
55
|
</Step>
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
|
|
57
|
+
<Step title="Read the zone id">
|
|
58
|
+
A zone id is `<domain>.<view>.<slot>.<placement>`. The last segment is the placement.
|
|
57
59
|
|
|
58
60
|
| Placement | Effect |
|
|
59
61
|
|-----------|--------|
|
|
60
62
|
| `before` | Renders before the built-in content of the zone |
|
|
61
63
|
| `after` | Renders after the built-in content |
|
|
62
64
|
|
|
63
|
-
Multiple `before`
|
|
65
|
+
Multiple `before` or `after` widgets on the same zone stack in registration order.
|
|
64
66
|
</Step>
|
|
67
|
+
|
|
65
68
|
<Step title="Reload the panel">
|
|
66
|
-
Start the project
|
|
69
|
+
Start the project and open any order in the vendor portal. Widget files hot-reload. The Copy link button appears in the summary section footer, and the rest of the page is untouched.
|
|
70
|
+
|
|
71
|
+
```bash Terminal
|
|
72
|
+
bun run dev
|
|
73
|
+
```
|
|
67
74
|
</Step>
|
|
68
75
|
</Steps>
|
|
69
76
|
|
|
70
77
|
## Order detail zones
|
|
71
78
|
|
|
72
|
-
|
|
79
|
+
These zones are mounted on the vendor order detail page.
|
|
73
80
|
|
|
74
81
|
| Zone | Where it renders |
|
|
75
82
|
|------|------------------|
|
|
@@ -77,27 +84,33 @@ Zones mounted on the vendor order detail page:
|
|
|
77
84
|
| `orders.detail.main.before` / `.after` | Around the main column (summary, payment, fulfillment) |
|
|
78
85
|
| `orders.detail.side.before` / `.after` | Around the sidebar (customer, activity) |
|
|
79
86
|
|
|
80
|
-
Each is passed the loaded `order` as `data`. The full, valid set is typed as `WidgetZoneId` and generated from the panel's own zone hosts
|
|
87
|
+
Each zone is passed the loaded `order` as `data`. The full, valid set is typed as `WidgetZoneId` and generated from the panel's own zone hosts. Let your editor autocomplete `zone:` to see every option.
|
|
88
|
+
|
|
89
|
+
<Tip>
|
|
90
|
+
A zone that no page renders can't be targeted and won't type-check. Set `zone: "not.a.zone"` and `tsc` (`bun run lint`) fails with a "not assignable to `WidgetZoneId`" error.
|
|
91
|
+
</Tip>
|
|
81
92
|
|
|
82
93
|
## Verify
|
|
83
94
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
95
|
+
Confirm the widget works end to end.
|
|
96
|
+
|
|
97
|
+
1. Open an order. The Copy link button renders in the summary section footer.
|
|
98
|
+
2. Click it. The link is copied and a toast appears.
|
|
99
|
+
3. Change the zone to `orders.detail.side.before` and reload. The button moves to the top of the sidebar.
|
|
100
|
+
4. Set `zone: "not.a.zone"`. `tsc` (`bun run lint`) fails with a "not assignable to `WidgetZoneId`" error.
|
|
101
|
+
5. Delete the file. The button disappears, and nothing else changed.
|
|
89
102
|
|
|
90
103
|
## FAQ
|
|
91
104
|
|
|
92
105
|
<AccordionGroup>
|
|
93
106
|
<Accordion title="What can I read from the order?">
|
|
94
|
-
The zone passes the loaded order as `data` (`HttpTypes.AdminOrder`)
|
|
107
|
+
The zone passes the loaded order as `data` (`HttpTypes.AdminOrder`): id, display id, totals, items, `payment_collections`, customer, and more. Build the link (or any UI) from it.
|
|
95
108
|
</Accordion>
|
|
96
109
|
<Accordion title="Can a block ship this instead of the host app?">
|
|
97
|
-
Yes. Put the same file in a [block](/rc/learn/blocks)'s `vendor_ui` entry under `src/widgets
|
|
110
|
+
Yes. Put the same file in a [block](/rc/learn/blocks)'s `vendor_ui` entry under `src/widgets/`. Installing the block adds the button with no wiring.
|
|
98
111
|
</Accordion>
|
|
99
112
|
<Accordion title="Can I render more than a button?">
|
|
100
|
-
The zone renders any React component
|
|
113
|
+
The zone renders any React component, such as a badge, an action menu, or a whole section. You have the full order in `data`.
|
|
101
114
|
</Accordion>
|
|
102
115
|
</AccordionGroup>
|
|
103
116
|
|
|
@@ -1,48 +1,49 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "
|
|
3
|
-
|
|
2
|
+
title: "How to Create Variant-Axis Attributes"
|
|
3
|
+
sidebarTitle: "Create Variant-Axis Attributes"
|
|
4
|
+
description: "Build an attribute catalog with a filterable attribute, a global variant axis, and an inline product-scoped axis."
|
|
4
5
|
---
|
|
5
6
|
|
|
6
|
-
Attributes give the shared catalog structured, typed data
|
|
7
|
+
Attributes give the shared catalog structured, typed data. For `multi_select` attributes, they can also drive variant generation.
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
This is a release-candidate feature built on Medusa's global product options (Medusa 2.16 preview). Details may still shift before the stable release.
|
|
10
|
-
</Warning>
|
|
9
|
+
This tutorial sets up the two kinds that matter most: a plain filterable attribute and a variant axis. A variant axis is a native Medusa global product option under the hood.
|
|
11
10
|
|
|
12
11
|
<Info>
|
|
13
|
-
**A variant axis IS a product option.** Attributes marked `is_variant_axis`
|
|
12
|
+
**A variant axis IS a product option.** Attributes marked `is_variant_axis` are not a parallel system bolted onto products. Each one mirrors one-to-one onto a Medusa `ProductOption` and its values. Variants are then built with Medusa's standard machinery (`variants[].options`), exactly as in a plain Medusa project. Non-axis attributes never become options. They attach as plain value links. This is why only `multi_select` attributes can be axes: an axis needs an enumerable set of values to combine into variants.
|
|
14
13
|
</Info>
|
|
15
14
|
|
|
16
15
|
## What you'll build
|
|
17
16
|
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
17
|
+
- **Material:** a global `multi_select`, filterable attribute used for storefront filtering.
|
|
18
|
+
- **Color:** a global variant axis shared across the catalog.
|
|
19
|
+
- **Fit:** an inline, product-scoped axis created on the fly from a product form.
|
|
21
20
|
|
|
22
21
|
## Global vs product-scoped
|
|
23
22
|
|
|
24
23
|
| Kind | Backed by | Appears in the global catalog? | Use for |
|
|
25
24
|
|------|-----------|-------------------------------|---------|
|
|
26
|
-
| Global attribute | Shared `ProductOption` (when axis) or value links | Yes | Data every product can use
|
|
25
|
+
| Global attribute | Shared `ProductOption` (when axis) or value links | Yes | Data every product can use, such as Material, Color, or Condition |
|
|
27
26
|
| Product-scoped attribute | Exclusive, product-owned option (when axis) | No | One-off fields or axes for a single product |
|
|
28
27
|
|
|
29
28
|
## Build the attribute catalog
|
|
30
29
|
|
|
31
30
|
<Steps>
|
|
32
31
|
<Step title="Create a filterable attribute">
|
|
33
|
-
In the Admin Panel, the operator owns the attribute catalog. Create **Material** as a global `multi_select` attribute with values like Cotton, Wool, Linen, and turn on `is_filterable`.
|
|
32
|
+
In the Admin Panel, the operator owns the attribute catalog. Create **Material** as a global `multi_select` attribute with values like Cotton, Wool, or Linen, and turn on `is_filterable`.
|
|
34
33
|
|
|
35
|
-
|
|
34
|
+
Global attributes (`product_id = null`) can be attached to any product and linked to categories, so the right attributes surface for the right product types.
|
|
35
|
+
|
|
36
|
+
Since it is not a variant axis, Material describes the product. It never generates variants.
|
|
36
37
|
</Step>
|
|
37
38
|
<Step title="Create a variant axis">
|
|
38
|
-
Create **Color** the same way, but enable `is_variant_axis`. This is only allowed for `multi_select` attributes
|
|
39
|
+
Create **Color** the same way, but enable `is_variant_axis`. This is only allowed for `multi_select` attributes. The platform rejects the flag on any other type.
|
|
39
40
|
|
|
40
|
-
Because Color is a **global** axis, it
|
|
41
|
+
Because Color is a **global** axis, it is backed by one shared product option. Every product that uses it links to that option, restricted to the subset of values the product actually offers. So "Color" means the same thing across the whole catalog, while one product can offer only Red and Blue.
|
|
41
42
|
</Step>
|
|
42
43
|
<Step title="Attach attributes to a product">
|
|
43
|
-
Products manage attributes through one **batch** endpoint that adds, removes, and updates in a single request
|
|
44
|
+
Products manage attributes through one **batch** endpoint that adds, removes, and updates in a single request.
|
|
44
45
|
|
|
45
|
-
```bash
|
|
46
|
+
```bash Terminal
|
|
46
47
|
curl -X POST "http://localhost:9000/vendor/products/prod_123/attributes/batch" \
|
|
47
48
|
-H "Authorization: Bearer <token>" \
|
|
48
49
|
-H "Content-Type: application/json" \
|
|
@@ -54,12 +55,12 @@ Attributes give the shared catalog structured, typed data — and for `multi_sel
|
|
|
54
55
|
}'
|
|
55
56
|
```
|
|
56
57
|
|
|
57
|
-
At product create time, the same entry shape is passed as a unified `attributes[]` array. Because Color is an axis, selecting Red and Blue makes them available as variant options
|
|
58
|
+
At product create time, the same entry shape is passed as a unified `attributes[]` array. Because Color is an axis, selecting Red and Blue makes them available as variant options. Variants are then defined with standard Medusa `variants[].options` mapping `"Color"` to `"Red"` or `"Blue"`.
|
|
58
59
|
</Step>
|
|
59
60
|
<Step title="Add an inline product-scoped axis">
|
|
60
|
-
Sometimes one product needs an axis that
|
|
61
|
+
Sometimes one product needs an axis that does not belong in the shared catalog. Define it **inline** by `title` instead of referencing an `id`.
|
|
61
62
|
|
|
62
|
-
```bash
|
|
63
|
+
```bash Terminal
|
|
63
64
|
curl -X POST "http://localhost:9000/vendor/products/prod_123/attributes/batch" \
|
|
64
65
|
-H "Authorization: Bearer <token>" \
|
|
65
66
|
-H "Content-Type: application/json" \
|
|
@@ -70,18 +71,18 @@ Attributes give the shared catalog structured, typed data — and for `multi_sel
|
|
|
70
71
|
}'
|
|
71
72
|
```
|
|
72
73
|
|
|
73
|
-
This creates a product-scoped attribute on the fly, backed by an **exclusive**, product-owned option. It
|
|
74
|
+
This creates a product-scoped attribute on the fly, backed by an **exclusive**, product-owned option. It does not appear in the global attribute list. It belongs to this product alone.
|
|
74
75
|
</Step>
|
|
75
76
|
</Steps>
|
|
76
77
|
|
|
77
78
|
<Note>
|
|
78
|
-
Attribute changes on products submitted by vendors flow through the same [change-request pipeline](/rc/learn/product-requests) as other product edits
|
|
79
|
+
Attribute changes on products submitted by vendors flow through the same [change-request pipeline](/rc/learn/product-requests) as other product edits: `ATTRIBUTE_ADD`, `ATTRIBUTE_UPDATE`, or `ATTRIBUTE_REMOVE` actions the operator reviews.
|
|
79
80
|
</Note>
|
|
80
81
|
|
|
81
82
|
## Verify
|
|
82
83
|
|
|
83
|
-
1. **Material** and **Color** appear in the Admin Panel's attribute catalog
|
|
84
|
-
2. The product detail shows Material as descriptive data and Color
|
|
84
|
+
1. **Material** and **Color** appear in the Admin Panel's attribute catalog. **Fit** does not, because it is product-scoped.
|
|
85
|
+
2. The product detail shows Material as descriptive data and Color and Fit as variant axes.
|
|
85
86
|
3. The product's variants combine the selected Color and Fit values, built from real product options.
|
|
86
87
|
4. The Store API exposes Material for filtering on product listings (`is_filterable`).
|
|
87
88
|
|
|
@@ -89,13 +90,13 @@ Attributes give the shared catalog structured, typed data — and for `multi_sel
|
|
|
89
90
|
|
|
90
91
|
<AccordionGroup>
|
|
91
92
|
<Accordion title="Why can't a text or toggle attribute be a variant axis?">
|
|
92
|
-
An axis needs an enumerable, finite value set to combine into variants
|
|
93
|
+
An axis needs an enumerable, finite value set to combine into variants, for example Red/Blue times Slim/Regular. Free text has no enumerable values, and a toggle's two fixed values rarely describe purchasable variations. Only `multi_select` qualifies, and the platform enforces it.
|
|
93
94
|
</Accordion>
|
|
94
95
|
<Accordion title="What's the difference between a value link and an option?">
|
|
95
|
-
Non-axis attributes attach to a product as plain **value links
|
|
96
|
+
Non-axis attributes attach to a product as plain **value links**: descriptive data for display and filtering. Axis attributes are mirrored onto real Medusa **product options**, which participate in variant generation. Same authoring UI, structurally different underneath.
|
|
96
97
|
</Accordion>
|
|
97
98
|
<Accordion title="Can I promote a product-scoped attribute to a global one later?">
|
|
98
|
-
Not automatically
|
|
99
|
+
Not automatically. A product-scoped axis is backed by an exclusive option owned by that product. Create the global attribute in the catalog and re-attach products to it. Treat inline attributes as intentionally local.
|
|
99
100
|
</Accordion>
|
|
100
101
|
</AccordionGroup>
|
|
101
102
|
|
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "Build
|
|
3
|
-
|
|
2
|
+
title: "How to Build a Block"
|
|
3
|
+
sidebarTitle: "Build a Block"
|
|
4
|
+
description: "Author a reusable feature as a block covering backend, panel UI, and docs, then build it into a registry and install it into any Mercur project."
|
|
4
5
|
---
|
|
5
6
|
|
|
6
|
-
Blocks are how features travel between Mercur projects
|
|
7
|
+
Blocks are how features travel between Mercur projects. You ship them as source code copied into the target project, not as npm packages you depend on.
|
|
8
|
+
|
|
9
|
+
Anything you build once, such as a module, workflows, routes, or panel pages, can be packaged as a block, published through a registry, and installed with `mercurjs add`. This tutorial builds a minimal "announcements" block and ships it through your own registry.
|
|
7
10
|
|
|
8
11
|
<Info>
|
|
9
|
-
**Blocks are source, not dependencies.** When someone installs your block, they get the files
|
|
12
|
+
**Blocks are source, not dependencies.** When someone installs your block, they get the files: editable, diffable, theirs. Updates are opt-in via `mercurjs diff` and `add --overwrite`, never forced through a lockfile. That is the trade: you give up automatic upgrades, and users gain full ownership. Design blocks so they read cleanly after install.
|
|
10
13
|
</Info>
|
|
11
14
|
|
|
12
15
|
## What you'll build
|
|
13
16
|
|
|
14
|
-
|
|
17
|
+
You build an `announcements` block containing a module (data model and service), a vendor API route, and a vendor portal page. Then you build it into registry JSON and install it into a Mercur project.
|
|
15
18
|
|
|
16
19
|
## File types and where they land
|
|
17
20
|
|
|
@@ -44,9 +47,11 @@ Each file in a block carries a `type` that maps to an alias in the consumer's `b
|
|
|
44
47
|
└── page.tsx # vendor portal page
|
|
45
48
|
```
|
|
46
49
|
|
|
47
|
-
Write the files exactly as they should land in a consumer's project
|
|
50
|
+
Write the files exactly as they should land in a consumer's project: real imports, real Medusa module definitions. The build step resolves imports and rewrites them to the consumer's path aliases at install time. For the panel page, use the same conventions as any [custom panel page](/rc/resources/tutorials/custom-panel-page): a default export plus a `config` for the sidebar entry.
|
|
48
51
|
</Step>
|
|
49
52
|
<Step title="Declare it in registry.json">
|
|
53
|
+
Add one entry per block to the `items` array.
|
|
54
|
+
|
|
50
55
|
```json registry.json
|
|
51
56
|
{
|
|
52
57
|
"$schema": "https://registry.mercurjs.com/registry.json",
|
|
@@ -70,20 +75,22 @@ Each file in a block carries a `type` that maps to an alias in the consumer's `b
|
|
|
70
75
|
}
|
|
71
76
|
```
|
|
72
77
|
|
|
73
|
-
Two fields do the heavy lifting
|
|
78
|
+
Two fields do the heavy lifting. **`type`** on each file decides where the file lands, and **`docs`** is the markdown shown after install. Put every manual step in `docs`: module registration, migrations, middleware, codegen. It is the only instruction the installer sees.
|
|
74
79
|
</Step>
|
|
75
80
|
<Step title="Build the registry">
|
|
76
|
-
|
|
81
|
+
Run the CLI build from the registry root.
|
|
82
|
+
|
|
83
|
+
```bash Terminal
|
|
77
84
|
bunx @mercurjs/cli@latest build
|
|
78
85
|
```
|
|
79
86
|
|
|
80
|
-
This reads `registry.json`, resolves each block's imports, embeds file contents, and writes one JSON per block into `r
|
|
87
|
+
This reads `registry.json`, resolves each block's imports, embeds file contents, and writes one JSON per block into `r/`: `r/announcements.json`, plus an index `r/registry.json`.
|
|
81
88
|
</Step>
|
|
82
89
|
<Step title="Host it">
|
|
83
|
-
Serve the `r/` directory from any static host (GitHub Pages, Vercel, S3
|
|
90
|
+
Serve the `r/` directory from any static host (GitHub Pages, Vercel, S3, or anything that makes `{name}.json` publicly reachable).
|
|
84
91
|
</Step>
|
|
85
92
|
<Step title="Install it into a project">
|
|
86
|
-
In a consumer project, register your registry in `blocks.json
|
|
93
|
+
In a consumer project, register your registry in `blocks.json`.
|
|
87
94
|
|
|
88
95
|
```json blocks.json
|
|
89
96
|
{
|
|
@@ -93,7 +100,9 @@ Each file in a block carries a `type` that maps to an alias in the consumer's `b
|
|
|
93
100
|
}
|
|
94
101
|
```
|
|
95
102
|
|
|
96
|
-
|
|
103
|
+
Then install the block.
|
|
104
|
+
|
|
105
|
+
```bash Terminal
|
|
97
106
|
bunx @mercurjs/cli@latest add @my-org/announcements
|
|
98
107
|
```
|
|
99
108
|
|
|
@@ -103,19 +112,21 @@ Each file in a block carries a `type` that maps to an alias in the consumer's `b
|
|
|
103
112
|
|
|
104
113
|
## Verify
|
|
105
114
|
|
|
115
|
+
Confirm the block built and installed correctly:
|
|
116
|
+
|
|
106
117
|
1. `r/announcements.json` exists after the build and embeds every file's content.
|
|
107
118
|
2. In the consumer project, the files landed under the alias-mapped paths and imports resolve.
|
|
108
119
|
3. After following your own `docs` steps (module registration, migrations, codegen), `bun run build` passes and the vendor portal shows the Announcements page.
|
|
109
|
-
4. `bunx @mercurjs/cli@latest diff @my-org/announcements` reports no changes
|
|
120
|
+
4. `bunx @mercurjs/cli@latest diff @my-org/announcements` reports no changes. The installed copy matches the registry.
|
|
110
121
|
|
|
111
122
|
## FAQ
|
|
112
123
|
|
|
113
124
|
<AccordionGroup>
|
|
114
125
|
<Accordion title="How do I depend on another block or an npm package?">
|
|
115
|
-
Other blocks go in `registryDependencies` (
|
|
126
|
+
Other blocks go in `registryDependencies` (for example `@my-org/reviews`). The CLI installs them in order automatically. NPM packages go in `dependencies`. The build also auto-detects them from your imports, so you rarely list transitive ones by hand.
|
|
116
127
|
</Accordion>
|
|
117
128
|
<Accordion title="Can I make the registry private?">
|
|
118
|
-
Yes
|
|
129
|
+
Yes. Use the object form with headers in the consumer's `blocks.json`: `{ "url": "…/{name}.json", "headers": { "Authorization": "Bearer ${REGISTRY_TOKEN}" } }`. The env var is resolved from the installer's environment. See [Registry](/rc/learn/registry).
|
|
119
130
|
</Accordion>
|
|
120
131
|
<Accordion title="How do consumers get updates to my block?">
|
|
121
132
|
They run `mercurjs diff <block>` to compare their local copy against your registry, then `add --overwrite` to take the new version. Because blocks are source, consumers with local edits merge deliberately rather than being force-upgraded.
|
|
@@ -1,23 +1,26 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "Add a
|
|
3
|
-
|
|
2
|
+
title: "How to Add a Custom API Route"
|
|
3
|
+
sidebarTitle: "Add a Custom Route"
|
|
4
|
+
description: "Add a backend endpoint, regenerate the route map, and call it from a panel page with full type safety."
|
|
4
5
|
---
|
|
5
6
|
|
|
6
|
-
Mercur's typed API client
|
|
7
|
+
Mercur's typed API client is generated from your actual route files, not hand-maintained. A custom endpoint you add to the API package becomes a first-class, fully typed client call after one codegen run.
|
|
8
|
+
|
|
9
|
+
This tutorial walks the whole loop: route, then codegen, then a typed call from a custom panel page.
|
|
7
10
|
|
|
8
11
|
<Info>
|
|
9
|
-
|
|
12
|
+
The contract is generated, not declared. You never write an interface for your endpoint. `mercurjs codegen` reads the route's handler and validators and emits the `Routes` type the client consumes, so the panel call site breaks at compile time the moment the backend changes. This loop is also what makes Mercur projects reliable targets for AI agents. See [Building with AI](/rc/resources/ai/overview).
|
|
10
13
|
</Info>
|
|
11
14
|
|
|
12
15
|
## What you'll build
|
|
13
16
|
|
|
14
|
-
A `GET /vendor/sales-summary` endpoint
|
|
17
|
+
A `GET /vendor/sales-summary` endpoint returns the seller's order count. You call it from a custom vendor portal page via `client.vendor.salesSummary.query()` with inferred types.
|
|
15
18
|
|
|
16
19
|
## Build the loop
|
|
17
20
|
|
|
18
21
|
<Steps>
|
|
19
22
|
<Step title="Create the route">
|
|
20
|
-
API routes follow Medusa's file conventions inside your API package. The URL path mirrors the directory path
|
|
23
|
+
API routes follow Medusa's file conventions inside your API package. The URL path mirrors the directory path.
|
|
21
24
|
|
|
22
25
|
```typescript packages/api/src/api/vendor/sales-summary/route.ts
|
|
23
26
|
import { AuthenticatedMedusaRequest, MedusaResponse } from "@medusajs/framework/http"
|
|
@@ -42,11 +45,13 @@ A `GET /vendor/sales-summary` endpoint returning the seller's order count, calle
|
|
|
42
45
|
Routes under `src/api/vendor/*` run behind the vendor authentication middleware, so `req.auth_context` identifies the calling seller. Use `src/api/admin/*` for operator endpoints and `src/api/store/*` for public storefront endpoints.
|
|
43
46
|
</Step>
|
|
44
47
|
<Step title="Regenerate the route map">
|
|
45
|
-
|
|
48
|
+
Run codegen to scan your route files.
|
|
49
|
+
|
|
50
|
+
```bash Terminal
|
|
46
51
|
bunx @mercurjs/cli@latest codegen
|
|
47
52
|
```
|
|
48
53
|
|
|
49
|
-
Codegen
|
|
54
|
+
Codegen rewrites the generated `Routes` type that your panel apps already import:
|
|
50
55
|
|
|
51
56
|
```typescript apps/vendor/src/lib/client.ts
|
|
52
57
|
import { createClient, type InferClient } from "@mercurjs/client"
|
|
@@ -60,14 +65,14 @@ A `GET /vendor/sales-summary` endpoint returning the seller's order count, calle
|
|
|
60
65
|
})
|
|
61
66
|
```
|
|
62
67
|
|
|
63
|
-
This file ships with the starter template
|
|
68
|
+
This file ships with the starter template, so you don't need to touch it. After codegen, `client.vendor.salesSummary` simply exists, typed.
|
|
64
69
|
|
|
65
70
|
<Tip>
|
|
66
71
|
Run `bunx @mercurjs/cli@latest codegen --watch` during development so the route map regenerates as you edit route files.
|
|
67
72
|
</Tip>
|
|
68
73
|
</Step>
|
|
69
74
|
<Step title="Call it from a panel page">
|
|
70
|
-
Drop a page into the vendor app and call the endpoint through the client. Route segments map to camelCase properties, and the
|
|
75
|
+
Drop a page into the vendor app and call the endpoint through the client. Route segments map to camelCase properties, and the terminal call chooses the HTTP method: `query` (GET), `mutate` (POST), or `delete` (DELETE).
|
|
71
76
|
|
|
72
77
|
```tsx apps/vendor/src/routes/sales-summary/page.tsx
|
|
73
78
|
import { useQuery } from "@tanstack/react-query"
|
|
@@ -97,7 +102,7 @@ A `GET /vendor/sales-summary` endpoint returning the seller's order count, calle
|
|
|
97
102
|
</div>
|
|
98
103
|
<div className="px-6 py-4">
|
|
99
104
|
<Text size="small" className="text-ui-fg-subtle">
|
|
100
|
-
Orders: {data?.order_count ?? "
|
|
105
|
+
Orders: {data?.order_count ?? "-"}
|
|
101
106
|
</Text>
|
|
102
107
|
</div>
|
|
103
108
|
</Container>
|
|
@@ -105,25 +110,32 @@ A `GET /vendor/sales-summary` endpoint returning the seller's order count, calle
|
|
|
105
110
|
}
|
|
106
111
|
```
|
|
107
112
|
|
|
108
|
-
`InferClientOutput` extracts the response type straight from the client method
|
|
113
|
+
`InferClientOutput` extracts the response type straight from the client method. Change the route's response shape, rerun codegen, and this component stops compiling until you update it.
|
|
109
114
|
</Step>
|
|
110
115
|
</Steps>
|
|
111
116
|
|
|
112
117
|
## Verify
|
|
113
118
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
119
|
+
Start the project and log into the vendor portal.
|
|
120
|
+
|
|
121
|
+
```bash Terminal
|
|
122
|
+
bun run dev
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Confirm each of the following:
|
|
126
|
+
|
|
127
|
+
1. **Sidebar entry:** Sales summary appears in the sidebar (the `config` export registered it), and the page shows the order count.
|
|
128
|
+
2. **Auth guard:** `curl http://localhost:9000/vendor/sales-summary` without a token returns an authentication error. The vendor middleware guards your route.
|
|
129
|
+
3. **Generated contract:** change the route to return `{ count: ... }` instead of `{ order_count: ... }`, rerun codegen, and confirm the page fails to type-check. That is the generated contract doing its job. Revert after.
|
|
118
130
|
|
|
119
131
|
## FAQ
|
|
120
132
|
|
|
121
133
|
<AccordionGroup>
|
|
122
134
|
<Accordion title="How do path parameters work in the client?">
|
|
123
|
-
Use `$`-prefixed segments: a route at `src/api/vendor/things/[id]/route.ts` is called as `client.vendor.things.$id.query({ $id: "thing_123" })`. The `$id` key is threaded into the URL path
|
|
135
|
+
Use `$`-prefixed segments: a route at `src/api/vendor/things/[id]/route.ts` is called as `client.vendor.things.$id.query({ $id: "thing_123" })`. The `$id` key is threaded into the URL path, and everything else in the object becomes query params (GET) or the JSON body (POST).
|
|
124
136
|
</Accordion>
|
|
125
137
|
<Accordion title="How do I handle errors from the client?">
|
|
126
|
-
Failed requests throw `ClientError` from `@mercurjs/client`, carrying `status`, `statusText`, and the backend's `message`. Wrap calls in try/catch or let TanStack Query surface the error.
|
|
138
|
+
Failed requests throw `ClientError` from `@mercurjs/client`, carrying `status`, `statusText`, and the backend's `message`. Wrap calls in try/catch or let TanStack Query surface the error.
|
|
127
139
|
</Accordion>
|
|
128
140
|
<Accordion title="Where do request validation schemas go?">
|
|
129
141
|
Follow Medusa conventions: a `validators.ts` next to the route with a Zod schema, wired through the route's middleware. Codegen reads validators too, so the client's input type reflects them.
|
|
@@ -133,8 +145,8 @@ A `GET /vendor/sales-summary` endpoint returning the seller's order count, calle
|
|
|
133
145
|
## Next steps
|
|
134
146
|
|
|
135
147
|
<CardGroup cols={2}>
|
|
136
|
-
<Card title="API
|
|
137
|
-
|
|
148
|
+
<Card title="API conventions" href="/references/api/conventions">
|
|
149
|
+
Authentication, pagination, field selection, and error shapes.
|
|
138
150
|
</Card>
|
|
139
151
|
<Card title="Extend a workflow" href="/rc/resources/customization/extend-a-workflow">
|
|
140
152
|
Put multi-step business logic behind your endpoint with rollback support.
|
|
@@ -1,23 +1,26 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: "
|
|
3
|
-
|
|
2
|
+
title: "How to Create a Custom Page"
|
|
3
|
+
sidebarTitle: "Create a Page"
|
|
4
|
+
description: "Add a page to the vendor portal or admin panel with file-based routing and let the dashboard SDK wire it into the sidebar."
|
|
4
5
|
---
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
Add a page to the vendor portal or admin panel from a single file.
|
|
8
|
+
|
|
9
|
+
The dashboard SDK scans `src/routes/` at build time, registers the route, and, if you export a `config`, adds it to the sidebar with a label and icon. There is no route table and no registration call.
|
|
7
10
|
|
|
8
11
|
<Info>
|
|
9
|
-
**Adding vs changing.** This tutorial *adds* a brand-new page
|
|
12
|
+
**Adding vs changing.** This tutorial *adds* a brand-new page, the right move for new features. To *change* an existing page, don't rebuild it. Add a [widget](/rc/resources/tutorials/add-a-widget) or a [custom field](/rc/resources/tutorials/extend-forms-and-tables) to inject into it. The [decision guide](/rc/resources/customization/extending-panels#choosing-your-extension-mechanism) compares every extension mechanism.
|
|
10
13
|
</Info>
|
|
11
14
|
|
|
12
15
|
## What you'll build
|
|
13
16
|
|
|
14
|
-
A `/reviews` page in the vendor portal with a sidebar entry
|
|
17
|
+
A `/reviews` page in the vendor portal with a sidebar entry, from a single file.
|
|
15
18
|
|
|
16
19
|
## Add the page
|
|
17
20
|
|
|
18
21
|
<Steps>
|
|
19
22
|
<Step title="Create the route file">
|
|
20
|
-
Drop a `page.tsx` under `src/routes/` in your vendor app. The file path becomes the URL, and the default export is the page
|
|
23
|
+
Drop a `page.tsx` under `src/routes/` in your vendor app. The file path becomes the URL, and the default export is the page.
|
|
21
24
|
|
|
22
25
|
```tsx apps/vendor/src/routes/reviews/page.tsx
|
|
23
26
|
import { Container, Heading } from "@medusajs/ui"
|
|
@@ -42,17 +45,23 @@ A `/reviews` page in the vendor portal with a sidebar entry — from a single fi
|
|
|
42
45
|
```
|
|
43
46
|
</Step>
|
|
44
47
|
<Step title="Let the SDK wire it up">
|
|
45
|
-
At build time the SDK registers the `/reviews` route, generates the sidebar item from `config` (`label`, `icon`, `rank`), and hot-reloads the route tree when you add or remove page files. Dynamic segments use brackets
|
|
48
|
+
At build time the SDK registers the `/reviews` route, generates the sidebar item from `config` (`label`, `icon`, `rank`), and hot-reloads the route tree when you add or remove page files. Dynamic segments use brackets: `src/routes/reviews/[id]/page.tsx` becomes `/reviews/:id`. The full path-to-route table is in [Extending Panels](/rc/resources/customization/extending-panels#routing-conventions).
|
|
46
49
|
</Step>
|
|
47
50
|
<Step title="Open it in the running panel">
|
|
48
|
-
Start the project
|
|
51
|
+
Start the project, then open the vendor portal.
|
|
52
|
+
|
|
53
|
+
```bash Terminal
|
|
54
|
+
bun run dev
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**Reviews** appears in the sidebar at the position set by `rank`, and `/reviews` renders your component.
|
|
49
58
|
</Step>
|
|
50
59
|
</Steps>
|
|
51
60
|
|
|
52
61
|
## Verify
|
|
53
62
|
|
|
54
63
|
1. The sidebar shows **Reviews** with the star icon.
|
|
55
|
-
2. Navigating to `/reviews` renders the page inside the standard panel layout
|
|
64
|
+
2. Navigating to `/reviews` renders the page inside the standard panel layout, with the sidebar and topbar intact.
|
|
56
65
|
3. Removing the `config` export keeps the route working but drops the sidebar item.
|
|
57
66
|
4. Deleting the file removes the route entirely.
|
|
58
67
|
|
|
@@ -60,13 +69,13 @@ A `/reviews` page in the vendor portal with a sidebar entry — from a single fi
|
|
|
60
69
|
|
|
61
70
|
<AccordionGroup>
|
|
62
71
|
<Accordion title="How do I fetch data on my page?">
|
|
63
|
-
Use the
|
|
72
|
+
Use the typed API client with TanStack Query. The panels already ship both. For a full loop including a custom backend endpoint, follow [Add a custom API route](/rc/resources/tutorials/custom-api-route).
|
|
64
73
|
</Accordion>
|
|
65
74
|
<Accordion title="Can the page live under /settings?">
|
|
66
|
-
Yes
|
|
75
|
+
Yes. Place the file under a `settings/` route segment and set `nested: "/settings"` in the config to group its sidebar item under Settings.
|
|
67
76
|
</Accordion>
|
|
68
77
|
<Accordion title="Does the same work for the admin panel?">
|
|
69
|
-
Identically
|
|
78
|
+
Identically. Drop the file in the admin app's `src/routes/` instead. Both panels use the same SDK and conventions.
|
|
70
79
|
</Accordion>
|
|
71
80
|
</AccordionGroup>
|
|
72
81
|
|