@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.
Files changed (283) hide show
  1. package/README.md +24 -0
  2. package/content/blocks.mdx +209 -0
  3. package/content/learn/architecture.mdx +215 -0
  4. package/content/learn/attributes.mdx +89 -0
  5. package/content/learn/blocks.mdx +99 -0
  6. package/content/learn/commissions.mdx +175 -0
  7. package/content/learn/concepts.mdx +84 -0
  8. package/content/learn/installation.mdx +117 -0
  9. package/content/learn/introduction.mdx +71 -0
  10. package/content/learn/offers.mdx +78 -0
  11. package/content/learn/order-groups.mdx +114 -0
  12. package/content/learn/payouts.mdx +175 -0
  13. package/content/learn/product-requests.mdx +82 -0
  14. package/content/learn/products.mdx +79 -0
  15. package/content/learn/registry.mdx +155 -0
  16. package/content/learn/seller-members.mdx +62 -0
  17. package/content/learn/sellers.mdx +118 -0
  18. package/content/migration/from-1-x-to-2-0.mdx +152 -0
  19. package/content/migration/from-2-0-to-2-1.mdx +105 -0
  20. package/content/migration/overview.mdx +58 -0
  21. package/content/references/api/admin/commission-rates/batch-commission-rules.mdx +70 -0
  22. package/content/references/api/admin/commission-rates/create-commission-rate.mdx +95 -0
  23. package/content/references/api/admin/commission-rates/delete-commission-rate.mdx +40 -0
  24. package/content/references/api/admin/commission-rates/list-commission-rates.mdx +92 -0
  25. package/content/references/api/admin/commission-rates/retrieve-commission-rate.mdx +70 -0
  26. package/content/references/api/admin/commission-rates/update-commission-rate.mdx +84 -0
  27. package/content/references/api/admin/members/list-members.mdx +61 -0
  28. package/content/references/api/admin/offers/batch-create-offers.mdx +130 -0
  29. package/content/references/api/admin/offers/delete-offer.mdx +40 -0
  30. package/content/references/api/admin/offers/list-offers.mdx +106 -0
  31. package/content/references/api/admin/offers/retrieve-offer.mdx +82 -0
  32. package/content/references/api/admin/order-groups/list-order-groups.mdx +77 -0
  33. package/content/references/api/admin/order-groups/retrieve-order-group.mdx +56 -0
  34. package/content/references/api/admin/orders/get-order-commission-lines.mdx +65 -0
  35. package/content/references/api/admin/orders/get-order-order-group.mdx +56 -0
  36. package/content/references/api/admin/orders/list-orders.mdx +79 -0
  37. package/content/references/api/admin/payouts/list-payouts.mdx +75 -0
  38. package/content/references/api/admin/payouts/retrieve-payout.mdx +62 -0
  39. package/content/references/api/admin/product-attributes/create-attribute-value.mdx +76 -0
  40. package/content/references/api/admin/product-attributes/create-product-attribute.mdx +99 -0
  41. package/content/references/api/admin/product-attributes/delete-attribute-value.mdx +52 -0
  42. package/content/references/api/admin/product-attributes/delete-product-attribute.mdx +40 -0
  43. package/content/references/api/admin/product-attributes/list-product-attributes.mdx +91 -0
  44. package/content/references/api/admin/product-attributes/retrieve-product-attribute.mdx +81 -0
  45. package/content/references/api/admin/product-attributes/update-attribute-value.mdx +66 -0
  46. package/content/references/api/admin/product-attributes/update-product-attribute.mdx +76 -0
  47. package/content/references/api/admin/product-changes/cancel-product-change.mdx +68 -0
  48. package/content/references/api/admin/product-changes/confirm-product-change.mdx +47 -0
  49. package/content/references/api/admin/products/batch-product-attributes.mdx +96 -0
  50. package/content/references/api/admin/products/confirm-product.mdx +59 -0
  51. package/content/references/api/admin/products/create-product-variant.mdx +78 -0
  52. package/content/references/api/admin/products/create-product.mdx +169 -0
  53. package/content/references/api/admin/products/delete-product-variant.mdx +48 -0
  54. package/content/references/api/admin/products/delete-product.mdx +40 -0
  55. package/content/references/api/admin/products/list-product-variants.mdx +91 -0
  56. package/content/references/api/admin/products/list-products.mdx +109 -0
  57. package/content/references/api/admin/products/preview-product.mdx +78 -0
  58. package/content/references/api/admin/products/reject-product.mdx +59 -0
  59. package/content/references/api/admin/products/request-product-changes.mdx +59 -0
  60. package/content/references/api/admin/products/retrieve-product-variant.mdx +73 -0
  61. package/content/references/api/admin/products/retrieve-product.mdx +96 -0
  62. package/content/references/api/admin/products/set-product-sellers.mdx +47 -0
  63. package/content/references/api/admin/products/update-product-variant.mdx +89 -0
  64. package/content/references/api/admin/products/update-product.mdx +133 -0
  65. package/content/references/api/admin/sellers/add-seller-member.mdx +63 -0
  66. package/content/references/api/admin/sellers/approve-seller.mdx +54 -0
  67. package/content/references/api/admin/sellers/create-seller.mdx +100 -0
  68. package/content/references/api/admin/sellers/delete-member-invite.mdx +42 -0
  69. package/content/references/api/admin/sellers/delete-professional-details.mdx +52 -0
  70. package/content/references/api/admin/sellers/invite-seller-member.mdx +63 -0
  71. package/content/references/api/admin/sellers/list-member-invites.mdx +71 -0
  72. package/content/references/api/admin/sellers/list-seller-members.mdx +71 -0
  73. package/content/references/api/admin/sellers/list-seller-products.mdx +85 -0
  74. package/content/references/api/admin/sellers/list-sellers.mdx +96 -0
  75. package/content/references/api/admin/sellers/remove-seller-member.mdx +42 -0
  76. package/content/references/api/admin/sellers/resend-member-invite.mdx +55 -0
  77. package/content/references/api/admin/sellers/retrieve-seller.mdx +81 -0
  78. package/content/references/api/admin/sellers/suspend-seller.mdx +60 -0
  79. package/content/references/api/admin/sellers/terminate-seller.mdx +60 -0
  80. package/content/references/api/admin/sellers/unsuspend-seller.mdx +52 -0
  81. package/content/references/api/admin/sellers/unterminate-seller.mdx +52 -0
  82. package/content/references/api/admin/sellers/update-seller.mdx +83 -0
  83. package/content/references/api/admin/sellers/upsert-payment-details.mdx +88 -0
  84. package/content/references/api/admin/sellers/upsert-professional-details.mdx +78 -0
  85. package/content/references/api/admin/sellers/upsert-seller-address.mdx +91 -0
  86. package/content/references/api/admin.mdx +134 -0
  87. package/content/references/api/conventions.mdx +109 -0
  88. package/content/references/api/store/carts/add-line-item.mdx +115 -0
  89. package/content/references/api/store/carts/add-shipping-methods.mdx +84 -0
  90. package/content/references/api/store/carts/apply-promotions.mdx +83 -0
  91. package/content/references/api/store/carts/complete-cart.mdx +98 -0
  92. package/content/references/api/store/offers/list-offers.mdx +161 -0
  93. package/content/references/api/store/offers/retrieve-offer.mdx +112 -0
  94. package/content/references/api/store/order-groups/list-order-groups.mdx +105 -0
  95. package/content/references/api/store/order-groups/retrieve-order-group.mdx +78 -0
  96. package/content/references/api/store/product-attributes/list-product-attributes.mdx +134 -0
  97. package/content/references/api/store/product-attributes/retrieve-product-attribute.mdx +78 -0
  98. package/content/references/api/store/product-categories/list-product-categories.mdx +126 -0
  99. package/content/references/api/store/product-categories/retrieve-product-category.mdx +79 -0
  100. package/content/references/api/store/products/list-products.mdx +184 -0
  101. package/content/references/api/store/products/retrieve-product.mdx +107 -0
  102. package/content/references/api/store/search/search.mdx +136 -0
  103. package/content/references/api/store/sellers/list-sellers.mdx +105 -0
  104. package/content/references/api/store/sellers/retrieve-seller.mdx +62 -0
  105. package/content/references/api/store/shipping-options/list-shipping-options.mdx +74 -0
  106. package/content/references/api/store.mdx +67 -0
  107. package/content/references/api/vendor/members/accept-member-invite.mdx +65 -0
  108. package/content/references/api/vendor/members/retrieve-current-member.mdx +51 -0
  109. package/content/references/api/vendor/members/update-current-member.mdx +70 -0
  110. package/content/references/api/vendor/offers/batch-create-offers.mdx +123 -0
  111. package/content/references/api/vendor/offers/batch-offer-inventory-items.mdx +103 -0
  112. package/content/references/api/vendor/offers/create-offer.mdx +141 -0
  113. package/content/references/api/vendor/offers/delete-offer.mdx +51 -0
  114. package/content/references/api/vendor/offers/list-offers.mdx +125 -0
  115. package/content/references/api/vendor/offers/retrieve-offer.mdx +74 -0
  116. package/content/references/api/vendor/offers/update-offer.mdx +82 -0
  117. package/content/references/api/vendor/orders/cancel-fulfillment.mdx +63 -0
  118. package/content/references/api/vendor/orders/cancel-order.mdx +56 -0
  119. package/content/references/api/vendor/orders/complete-order.mdx +55 -0
  120. package/content/references/api/vendor/orders/create-fulfillment.mdx +76 -0
  121. package/content/references/api/vendor/orders/create-shipment.mdx +99 -0
  122. package/content/references/api/vendor/orders/get-order-commission-lines.mdx +66 -0
  123. package/content/references/api/vendor/orders/list-order-changes.mdx +75 -0
  124. package/content/references/api/vendor/orders/list-orders.mdx +103 -0
  125. package/content/references/api/vendor/orders/mark-fulfillment-delivered.mdx +62 -0
  126. package/content/references/api/vendor/orders/preview-order.mdx +65 -0
  127. package/content/references/api/vendor/orders/retrieve-order.mdx +84 -0
  128. package/content/references/api/vendor/payout-accounts/create-onboarding.mdx +68 -0
  129. package/content/references/api/vendor/payout-accounts/create-payout-account.mdx +59 -0
  130. package/content/references/api/vendor/payout-accounts/retrieve-payout-account-by-id.mdx +60 -0
  131. package/content/references/api/vendor/payout-accounts/retrieve-payout-account.mdx +77 -0
  132. package/content/references/api/vendor/payouts/list-payouts.mdx +90 -0
  133. package/content/references/api/vendor/payouts/retrieve-payout.mdx +63 -0
  134. package/content/references/api/vendor/product-attributes/list-product-attributes.mdx +135 -0
  135. package/content/references/api/vendor/product-attributes/retrieve-product-attribute.mdx +71 -0
  136. package/content/references/api/vendor/product-variants/list-variants.mdx +136 -0
  137. package/content/references/api/vendor/products/batch-product-attributes.mdx +104 -0
  138. package/content/references/api/vendor/products/cancel-product-change.mdx +62 -0
  139. package/content/references/api/vendor/products/create-product-variant.mdx +92 -0
  140. package/content/references/api/vendor/products/create-product.mdx +197 -0
  141. package/content/references/api/vendor/products/delete-product-variant.mdx +68 -0
  142. package/content/references/api/vendor/products/delete-product.mdx +62 -0
  143. package/content/references/api/vendor/products/list-product-variants.mdx +114 -0
  144. package/content/references/api/vendor/products/list-products.mdx +163 -0
  145. package/content/references/api/vendor/products/preview-product.mdx +61 -0
  146. package/content/references/api/vendor/products/retrieve-product-variant.mdx +76 -0
  147. package/content/references/api/vendor/products/retrieve-product.mdx +69 -0
  148. package/content/references/api/vendor/products/update-product-variant.mdx +104 -0
  149. package/content/references/api/vendor/products/update-product.mdx +148 -0
  150. package/content/references/api/vendor/sellers/create-seller.mdx +150 -0
  151. package/content/references/api/vendor/sellers/delete-professional-details.mdx +54 -0
  152. package/content/references/api/vendor/sellers/invite-seller-member.mdx +67 -0
  153. package/content/references/api/vendor/sellers/list-member-invites.mdx +82 -0
  154. package/content/references/api/vendor/sellers/list-seller-members.mdx +80 -0
  155. package/content/references/api/vendor/sellers/list-sellers.mdx +71 -0
  156. package/content/references/api/vendor/sellers/remove-seller-member.mdx +48 -0
  157. package/content/references/api/vendor/sellers/retrieve-current-seller-member.mdx +59 -0
  158. package/content/references/api/vendor/sellers/retrieve-current-seller.mdx +69 -0
  159. package/content/references/api/vendor/sellers/select-seller.mdx +44 -0
  160. package/content/references/api/vendor/sellers/update-current-seller.mdx +108 -0
  161. package/content/references/api/vendor/sellers/update-member-role.mdx +51 -0
  162. package/content/references/api/vendor/sellers/upsert-payment-details.mdx +74 -0
  163. package/content/references/api/vendor/sellers/upsert-professional-details.mdx +70 -0
  164. package/content/references/api/vendor/sellers/upsert-seller-address.mdx +81 -0
  165. package/content/references/api/vendor.mdx +150 -0
  166. package/content/references/configuration.mdx +155 -0
  167. package/content/references/modules/commission.mdx +106 -0
  168. package/content/references/modules/custom-fields.mdx +45 -0
  169. package/content/references/modules/media.mdx +55 -0
  170. package/content/references/modules/offer.mdx +64 -0
  171. package/content/references/modules/payout.mdx +121 -0
  172. package/content/references/modules/product-attribute.mdx +111 -0
  173. package/content/references/modules/product-edit.mdx +80 -0
  174. package/content/references/modules/search.mdx +112 -0
  175. package/content/references/modules/seller.mdx +175 -0
  176. package/content/references/overview.mdx +70 -0
  177. package/content/references/workflows/cart/add-seller-shipping-method-to-cart.mdx +44 -0
  178. package/content/references/workflows/cart/complete-cart-with-split-orders.mdx +36 -0
  179. package/content/references/workflows/cart/list-seller-shipping-options-for-cart.mdx +39 -0
  180. package/content/references/workflows/cart/update-cart-seller-promotions.mdx +42 -0
  181. package/content/references/workflows/commission/batch-commission-rules.mdx +45 -0
  182. package/content/references/workflows/commission/create-commission-rates.mdx +41 -0
  183. package/content/references/workflows/commission/delete-commission-rates.mdx +34 -0
  184. package/content/references/workflows/commission/refresh-order-commission-lines.mdx +30 -0
  185. package/content/references/workflows/commission/update-commission-rates.mdx +35 -0
  186. package/content/references/workflows/media/set-category-images.mdx +41 -0
  187. package/content/references/workflows/media/set-collection-images.mdx +41 -0
  188. package/content/references/workflows/member/accept-member-invite.mdx +33 -0
  189. package/content/references/workflows/member/add-seller-member.mdx +30 -0
  190. package/content/references/workflows/member/create-member-invites.mdx +34 -0
  191. package/content/references/workflows/member/delete-member-invite.mdx +24 -0
  192. package/content/references/workflows/member/remove-seller-member.mdx +28 -0
  193. package/content/references/workflows/member/resend-member-invite.mdx +28 -0
  194. package/content/references/workflows/member/update-member-role.mdx +28 -0
  195. package/content/references/workflows/member/update-member.mdx +35 -0
  196. package/content/references/workflows/offer/batch-offer-inventory-items.mdx +58 -0
  197. package/content/references/workflows/offer/create-offers.mdx +63 -0
  198. package/content/references/workflows/offer/delete-offers.mdx +35 -0
  199. package/content/references/workflows/offer/update-offers.mdx +51 -0
  200. package/content/references/workflows/order/cancel-order-fulfillment.mdx +34 -0
  201. package/content/references/workflows/order/confirm-claim-request.mdx +25 -0
  202. package/content/references/workflows/order/confirm-exchange-request.mdx +25 -0
  203. package/content/references/workflows/order/confirm-order-edit-request.mdx +25 -0
  204. package/content/references/workflows/order/confirm-return-receive.mdx +25 -0
  205. package/content/references/workflows/order/create-order-fulfillment.mdx +45 -0
  206. package/content/references/workflows/order-group/get-order-group-detail.mdx +29 -0
  207. package/content/references/workflows/order-group/get-order-groups-list.mdx +36 -0
  208. package/content/references/workflows/overview.mdx +72 -0
  209. package/content/references/workflows/payout/create-onboarding.mdx +36 -0
  210. package/content/references/workflows/payout/create-payout-account.mdx +33 -0
  211. package/content/references/workflows/payout/create-payout.mdx +30 -0
  212. package/content/references/workflows/payout/process-payout-for-webhook.mdx +32 -0
  213. package/content/references/workflows/product/confirm-products.mdx +46 -0
  214. package/content/references/workflows/product/create-products.mdx +63 -0
  215. package/content/references/workflows/product/link-sellers-to-product-category.mdx +40 -0
  216. package/content/references/workflows/product/link-sellers-to-product.mdx +40 -0
  217. package/content/references/workflows/product/reject-product.mdx +46 -0
  218. package/content/references/workflows/product/request-product-change.mdx +46 -0
  219. package/content/references/workflows/product-attribute/add-product-attributes-to-product.mdx +49 -0
  220. package/content/references/workflows/product-attribute/create-and-link-product-attributes-to-product.mdx +46 -0
  221. package/content/references/workflows/product-attribute/create-product-attribute-values.mdx +43 -0
  222. package/content/references/workflows/product-attribute/create-product-attributes.mdx +56 -0
  223. package/content/references/workflows/product-attribute/delete-product-attribute-values.mdx +30 -0
  224. package/content/references/workflows/product-attribute/delete-product-attributes.mdx +30 -0
  225. package/content/references/workflows/product-attribute/remove-product-attributes-from-product.mdx +29 -0
  226. package/content/references/workflows/product-attribute/update-product-attribute-values.mdx +44 -0
  227. package/content/references/workflows/product-attribute/update-product-attributes-on-product.mdx +41 -0
  228. package/content/references/workflows/product-attribute/update-product-attributes.mdx +48 -0
  229. package/content/references/workflows/product-attribute/upsert-product-attribute-values.mdx +43 -0
  230. package/content/references/workflows/product-edit/auto-confirm-product-change.mdx +39 -0
  231. package/content/references/workflows/product-edit/cancel-product-change.mdx +49 -0
  232. package/content/references/workflows/product-edit/confirm-product-change.mdx +57 -0
  233. package/content/references/workflows/product-edit/create-product-change.mdx +72 -0
  234. package/content/references/workflows/product-edit/reject-product-change.mdx +54 -0
  235. package/content/references/workflows/product-edit/stage-product-change.mdx +75 -0
  236. package/content/references/workflows/seller/approve-seller.mdx +34 -0
  237. package/content/references/workflows/seller/create-seller-account.mdx +59 -0
  238. package/content/references/workflows/seller/create-seller-defaults.mdx +22 -0
  239. package/content/references/workflows/seller/create-sellers.mdx +65 -0
  240. package/content/references/workflows/seller/delete-seller-professional-details.mdx +37 -0
  241. package/content/references/workflows/seller/delete-sellers.mdx +24 -0
  242. package/content/references/workflows/seller/invite-seller.mdx +28 -0
  243. package/content/references/workflows/seller/suspend-seller.mdx +35 -0
  244. package/content/references/workflows/seller/terminate-seller.mdx +35 -0
  245. package/content/references/workflows/seller/unsuspend-seller.mdx +34 -0
  246. package/content/references/workflows/seller/unterminate-seller.mdx +34 -0
  247. package/content/references/workflows/seller/update-seller-address.mdx +55 -0
  248. package/content/references/workflows/seller/update-seller-payment-details.mdx +52 -0
  249. package/content/references/workflows/seller/update-seller-professional-details.mdx +48 -0
  250. package/content/references/workflows/seller/update-sellers.mdx +57 -0
  251. package/content/resources/ai/llms.mdx +74 -0
  252. package/content/resources/ai/mcp.mdx +152 -0
  253. package/content/resources/ai/overview.mdx +97 -0
  254. package/content/resources/customization/custom-fields.mdx +182 -0
  255. package/content/resources/customization/extend-a-workflow.mdx +39 -0
  256. package/content/resources/customization/extending-panels.mdx +309 -0
  257. package/content/resources/deployment/medusa-cloud.mdx +167 -0
  258. package/content/resources/integrations/notifications.mdx +39 -0
  259. package/content/resources/integrations/search.mdx +122 -0
  260. package/content/resources/integrations/stripe-connect.mdx +395 -0
  261. package/content/resources/tutorials/add-a-block.mdx +74 -0
  262. package/content/resources/tutorials/attributes-and-variant-axes.mdx +111 -0
  263. package/content/resources/tutorials/build-a-block.mdx +134 -0
  264. package/content/resources/tutorials/configure-commissions.mdx +127 -0
  265. package/content/resources/tutorials/custom-api-route.mdx +142 -0
  266. package/content/resources/tutorials/custom-panel-page.mdx +78 -0
  267. package/content/resources/tutorials/first-marketplace.mdx +45 -0
  268. package/content/resources/tutorials/handle-product-requests.mdx +80 -0
  269. package/content/resources/tutorials/import-export-products.mdx +96 -0
  270. package/content/resources/tutorials/master-products-and-offers.mdx +89 -0
  271. package/content/resources/tutorials/recompose-a-page.mdx +129 -0
  272. package/content/resources/tutorials/replace-panel-components.mdx +116 -0
  273. package/content/resources/tutorials/seller-payouts-stripe.mdx +89 -0
  274. package/content/telemetry.mdx +67 -0
  275. package/content/tools/api-client.mdx +155 -0
  276. package/content/tools/cli.mdx +196 -0
  277. package/content/tools/dashboard-sdk.mdx +35 -0
  278. package/content/user-guide/admin/overview.mdx +23 -0
  279. package/content/user-guide/admin/stores.mdx +193 -0
  280. package/content/user-guide/vendor/overview.mdx +23 -0
  281. package/content/user-guide/vendor/stores.mdx +209 -0
  282. package/llms.txt +307 -0
  283. 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
+ ![Medusa Cloud welcome screen](/images/v2/cloud_1.png)
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
+ ![Choose repository](/images/v2/cloud_2.png)
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
+ ![Configure project — name, region, Medusa root directory](/images/v2/cloud_3.png)
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
+ ![Environment variables](/images/v2/cloud_4.png)
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>