product-import-export block adds CSV import and export to the Vendor Portal: API routes, workflows built on Medusa’s product CSV steps, and drawer UIs wired into the product list.
This block is also a masterclass in Mercur’s extension model. It ships backend workflows and routes into your API package, and it overrides the vendor
/products page by dropping a route file that re-composes the built-in page’s compound slots — adding Import/Export buttons while keeping the stock table untouched. After installing, read its source; you own every file.What you’ll build
A vendor product list with Import and Export header buttons, a working CSV round-trip, and the block’s source code in your project.Install and wire the block
Install the block
blocks.json aliases — workflows and routes into the API package, pages and hooks into the vendor app.Install its dependencies
The block uses Medusa’s CSV flows and
multer for uploads. Install them in the API workspace, not the project root:Register the middleware
The import route needs its upload middleware. Add it to your API’s
middlewares.ts:packages/api/src/api/middlewares.ts
Regenerate types
The block added
POST /vendor/products/import and GET /vendor/products/export. Regenerate the route map so the vendor app’s typed client knows about them:No new modules and no migrations — the block reuses Medusa’s built-in product CSV steps, so there’s nothing to add to
medusa-config.ts for this one. Always read a block’s post-install output: each block declares its own setup steps.Run a round-trip
Start the project and open the Vendor Portal’s Products page — the header now shows Import and Export next to Create.
- Export — opens the drawer at
/products/exportand downloads the seller’s current products as CSV. - Edit the CSV: tweak a title, add a row.
- Import — the drawer at
/products/importaccepts the file, validates rows, and shows an import summary before applying.
Verify
- The Products header shows Import and Export buttons; the rest of the page (search, filters, pagination) behaves exactly as before.
- The exported CSV contains the seller’s products — and only theirs; the workflow scopes to the authenticated seller.
- After importing the edited CSV, the changed title appears in the product list.
- The block’s source lives in your repo (e.g.
packages/api/src/workflows/import-seller-products.ts,apps/vendor/src/routes/products/page.tsx) — runbunx @mercurjs/cli@rc diff product-import-exportto compare against the registry later.
FAQ
Can I customize the CSV columns or validation?
Can I customize the CSV columns or validation?
Yes — the block is source code in your repo. The import workflow (
import-seller-products.ts) and its validation step are yours to edit; the drawer UI under routes/products/import/ includes the CSV template helper you can extend.I already customized my /products page — will the block overwrite it?
I already customized my /products page — will the block overwrite it?
The block ships its own
routes/products/page.tsx. If you already have one, the CLI asks before overwriting (or use --overwrite explicitly). Merge by hand in that case: keep your composition and add the block’s Import/Export buttons to your HeaderActions.Does import respect the product approval flow?
Does import respect the product approval flow?
Imported products enter through the same vendor create path as manual submissions — so they follow the product-request pipeline and land as
proposed for operator review, not as instantly published records.Next steps
Re-compose a built-in page
The page-override technique this block uses, explained step by step.
Build your own block
Package a feature like this one and publish it to your own registry.