Link BCMS entries to products by slot (e.g. rich_description, recommended_blogs), with per-slot template allowlists in admin, and serve resolved content through store API routes.
- Medusa
^2.19 - Node
>=20.19.0 - BCMS API key
npm install @thebcms/medusa-pluginRegister in medusa-config.ts:
import { defineConfig, loadEnv } from "@medusajs/framework/utils"
loadEnv(process.env.NODE_ENV || "development", process.cwd())
module.exports = defineConfig({
plugins: [
{
resolve: "@thebcms/medusa-plugin",
options: {
apiKey: process.env.BCMS_API_KEY,
},
},
],
})Run migrations:
npx medusa db:migrate| Option | Type | Default | Description |
|---|---|---|---|
apiKey |
string |
— | BCMS API key (required for BCMS calls). |
cmsOrigin |
string |
BCMS default | Your BCMS instance URL. |
useMemCache |
boolean |
true |
Client cache. Set false for live preview. |
debug |
boolean |
false |
Verbose BCMS client logs. |
- Settings → BCMS — define slots and which templates each slot may use. No slots exist until you add them. An empty template list on a slot means all templates are allowed.
- Products → BCMS content — link one or more BCMS entries per slot.
Auth: Medusa publishable API key (via JS SDK).
| Method | Path | Description |
|---|---|---|
| GET | /store/bcms/products/:id |
Product + resolved entries in bcms.slots. |
| GET | /store/bcms/entries/:id?template= |
Single entry by id. |
| GET | /store/bcms/pages/:slug?template= |
Single entry by slug. |
Standalone entry/page routes only allow templates configured on at least one slot (or all templates if any slot has an empty allowlist). Linked entries on the product route are always returned.
import Medusa from "@medusajs/js-sdk"
const sdk = new Medusa({
baseUrl: process.env.NEXT_PUBLIC_MEDUSA_BACKEND_URL!,
publishableKey: process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY!,
})
const { product, bcms } = await sdk.client.fetch(
`/store/bcms/products/${productId}`
)
const richText = bcms.slots["rich_description"]?.[0]?.entry
const blogs = bcms.slots["recommended_blogs"] ?? []Query linked entries in custom routes:
const { data } = await query.graph({
entity: "product",
fields: ["id", "title", "bcms_links.*"],
filters: { id: productId },
})Types:
import type {
BcmsModuleOptions,
BcmsLinkPayload,
BcmsSettingPayload,
} from "@thebcms/medusa-plugin/modules/bcms"npm install
npx medusa plugin:publish # local yalc registry
npx medusa plugin:develop # watch + rebuildIn a Medusa app:
npx medusa plugin:add @thebcms/medusa-plugin
npx medusa db:migrate