Help us improve
Share bugs, ideas, or general feedback.
From bynder
The Bynder + Contentful integration playbook — the most common Slalom Composable DXP pattern. Covers the OOTB Bynder app for Contentful, when to extend it with custom Compact View embeds, the asset-reference data shape persisted in Contentful entries, derivative selection at the CMS field level, webhook-driven cache invalidation between the two systems, multi-environment / multi-brand integration patterns, and the optimization-engagement signals that point to a broken pairing. Use this skill any time the engagement involves Bynder and Contentful together — greenfield stand-up, integration repair, or upgrading an existing OOTB-only deployment to a custom-embed pattern.
npx claudepluginhub bpainter/composable-dxp-claude-marketplace --plugin bynderHow this skill is triggered — by the user, by Claude, or both
Slash command
/bynder:bynder-contentful-pairingThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
This is the bridge skill. Most Slalom Composable DXP engagements pair Bynder (DAM source of truth) with Contentful (CMS source of truth for everything else). The OOTB Bynder app for Contentful is the starting point; almost every production deployment extends it with custom configuration, custom Compact View embeds for advanced flows, or webhook-driven sync between the two systems.
Guides technical evaluation of code review feedback: read fully, restate for understanding, verify against codebase, respond with reasoning or pushback before implementing.
Share bugs, ideas, or general feedback.
This is the bridge skill. Most Slalom Composable DXP engagements pair Bynder (DAM source of truth) with Contentful (CMS source of truth for everything else). The OOTB Bynder app for Contentful is the starting point; almost every production deployment extends it with custom configuration, custom Compact View embeds for advanced flows, or webhook-driven sync between the two systems.
This skill puts you in the role of the engineer who owns the integration end-to-end. Default posture: install OOTB, identify gaps against the editorial flow, layer custom UCV embeds for the gaps, wire webhooks for downstream sync.
Pair with bynder-marketplace-connectors (the OOTB starting point), bynder-compact-view (the custom embed substrate), bynder-asset-model (the metaproperty schema CMS field controls filter on), bynder-derivatives (what URL flows from DAM to CMS), bynder-webhooks-events (the bidirectional sync), and the contentful plugin's contentful-content-model (how Contentful entries reference Bynder assets) and contentful-react-wrapper (how the front end consumes them).
asset.updated → invalidate Contentful entries that reference it. Contentful Entry.publish → optionally tag/categorize the asset back in Bynder.master should reference the same Bynder portal that production reads from. Non-prod Contentful → non-prod Bynder portal or sandbox. See the multi-environment notes below.Available at the Bynder Marketplace and the Contentful Marketplace.
RightsStatus=Cleared) to constrain choices.Contentful side:
1. Install the Bynder app definition (Apps → marketplace → Bynder).
2. Configure the app: Bynder portal URL, default asset types, default derivative.
3. Create a field on your content type:
- Type: JSON object
- Field control: Bynder asset (provided by the app)
4. Optionally constrain with field-level config (specific filters per content type).
Bynder side:
1. Set up the Compact View configuration in the portal (return-derivative,
default filters per integration).
2. Confirm the API user / token used by the app has scope to read assets and
metaproperties.
3. Set focal points on photographic assets so derivative crops behave.
Walk an editor through picking an asset before declaring done.
Build a Contentful App Framework app that hosts a custom field control wrapping UCV. Patterns:
When the entry's content type implies a single brand context (a single-brand client's Article type), pre-filter the picker:
// in your Contentful App Framework custom field control
BynderCompactView.open({
defaultMetapropertyOptions: [BRAND_OPTION_IDS[entry.fields.brand['en-US']]],
// ...
});
Editors only see assets from the right brand. Removes a class of editorial mistakes.
Some flows need the editor to choose which derivative variant goes into the field — e.g., the entry has a heroAsset field where the editor picks an image and then specifies whether to use the wide-crop, square-crop, or portrait-crop derivative.
function HeroAssetField() {
const [value, setValue] = useFieldValue<HeroAssetFieldValue>();
// ...
return (
<>
<PreviewCard asset={value?.asset} />
<CropSelector
options={['wide', 'square', 'portrait']}
value={value?.crop}
onChange={(crop) => setValue({ ...value, crop, derivativeUrl: value.asset.thumbnails[`hero_${crop}`] })}
/>
</>
);
}
Single-field-multi-asset using MultiSelect mode:
BynderCompactView.open({
mode: 'MultiSelect',
// ...
onSuccess: (assets) => {
setValue(assets.map((a) => ({ assetId: a.id, derivativeUrl: a.thumbnails.web_card_md, alt: a.description })));
},
});
The Contentful field type is JSON object with an array shape.
Refuse selections that don't meet requirements (e.g., dimensions too small for the design slot):
onSuccess: (assets) => {
const a = assets[0];
if (a.width < 1920) {
sdk.dialogs.openAlert({
title: 'Asset too small',
message: 'This slot needs ≥ 1920px wide. Pick a higher-resolution asset.',
});
return;
}
setValue({ /* ... */ });
};
Standardize across content types. A bynderAsset JSON shape:
{
"assetId": "5KsDBWseXY6QegucYAoacS",
"name": "Hero — Composable 2026",
"alt": "Two engineers reviewing a composable architecture diagram",
"type": "image",
"width": 4000,
"height": 2250,
"derivatives": {
"hero": "https://...?...&w=2560&fm=webp",
"card": "https://...?...&w=1024&fm=webp",
"thumbnail": "https://...?...&w=320&fm=webp"
},
"version": "2026-04-08T12:00:00Z" // Bynder's dateModified at pick time
}
The version field powers staleness detection on the front end and the webhook-invalidation logic.
For multi-asset fields (galleries), an array of the same shape.
The OOTB app doesn't sync; you wire it.
Bynder webhook: asset.updated → webhook receiver
→ look up Contentful entries that reference this asset (by Bynder assetId in JSON field values — query against Contentful's CMA)
→ for each entry, optionally re-fetch the asset from Bynder, update the cached derivative URLs, save (don't publish — let editors see the change in preview)
→ trigger on-demand revalidation on the front end (Vercel/Next.js revalidateTag for the affected entries)
The Contentful CMA query is annoying — JSON-field contents aren't indexed for query. Two practical strategies:
assetId → entryId[]. Build the index from a one-time scan + maintain incrementally on Contentful publish events.Symbol-array field. Now CMA can query by tag value.Strategy 2 is simpler if you control the content model; strategy 1 if the model is fixed.
Less common, but high-value where the brand team wants to know "this asset is in production" — fire a Contentful Entry.publish webhook, look up the referenced Bynder assets, and stamp them with a LastUsedInProduction metaproperty or add them to a "currently in use" Bynder collection. Powers downstream analytics ("which assets are actually live?").
See bynder-webhooks-events for the receiver patterns.
Contentful and Bynder both have environment models, but they don't quite line up.
| Contentful concept | Bynder equivalent | Reality |
|---|---|---|
master environment | Production portal | One-to-one |
staging / dev environment | Sandbox portal (if plan supports) or shared production portal with restricted folders / sub-portal | Often shared — the practical effect is staging Contentful references production Bynder |
| Environment alias | n/a | Contentful concept only |
| Sub-portal | n/a | Bynder concept only |
Slalom default:
master alias) → Production Bynder portal.staging, dev) → Same Bynder production portal, but with a permission profile that restricts non-prod tokens to a subset of assets (e.g., a Sandbox collection) so non-prod CMS doesn't accidentally publish unreleased assets.Document the environment mapping in the integration plan and walk the editor team through it. The number-one cause of "the staging site shows the wrong image" is environment mismatch.
When the client has multiple brands:
Brand metaproperty driving partition.brand reference field.Pick the same partition strategy on both sides where possible.
| Bynder | Contentful | Use |
|---|---|---|
| Sub-portal per brand | Space per brand | Strong isolation; multi-brand-as-multi-business-unit |
| Single portal + Brand metaproperty | Single space + brand field | Brand-aware shared assets; faster to build, more cross-brand surface |
| Single portal | Space per brand | Centralized asset pool, brand-isolated content |
| Sub-portal per brand | Single space | Brand-isolated assets, shared content scaffold (rare and brittle) |
# Bynder + Contentful Integration Plan: [Project]
## Engagement shape
[Greenfield + Contentful | Optimization | Adding Bynder to existing Contentful | Adding Contentful to existing Bynder]
## Baseline (OOTB)
- Contentful app installed: [yes / planned]
- Bynder portal config done: [yes / planned]
- Default asset types, derivatives, filters: [...]
## Custom embeds (if any)
- [Field name on content type]: [why custom; configuration]
## Asset-reference shape
[The JSON envelope persisted in Contentful entries.]
## Webhook strategy
- Bynder → Contentful invalidation: [strategy 1 (external index) | strategy 2 (tag on entry)]
- Contentful → Bynder (if any): [LastUsedInProduction stamp | collection membership]
## Multi-environment mapping
| Contentful env | Bynder portal/profile |
| ... | ... |
## Multi-brand mapping (if applicable)
[Bynder partition × Contentful partition]
## Test plan
- Editor picks asset, saves entry, publishes — front end renders correct derivative
- Bynder asset updated — front end reflects within [N] minutes
- Bynder asset deleted — Contentful entry surfaces clear error
- Multi-env: pick from non-prod Bynder, never bleeds into prod Contentful
These are the prompts that point to a broken-pairing optimization engagement:
| Signal | Diagnosis | Fix |
|---|---|---|
| "Editors download from Bynder, edit, re-upload" | Compact View not exposing the right filters / derivatives | Custom embed with editorial-flow-aware config |
| "Asset updates in Bynder don't show on the site" | No webhook-driven invalidation | Wire webhooks → external index or entry-tag strategy |
| "We can't tell which assets are actually live" | No Contentful → Bynder reverse signal | Stamp assets on entry publish |
| "Picker shows internal assets that legal hasn't cleared" | OOTB without portal-level default filter | Add RightsStatus=Cleared default filter on portal Compact View config |
| "Wrong brand's assets in the picker" | Single-portal multi-brand without filtering | Pre-filter UCV by Brand on entry / content type |
| "Different image variants in different places" | No standardized derivative selection | Standardize asset-reference shape; rebuild custom field control |
| "Staging site shows production assets" | Environment mismatch | Document and enforce env mapping |
bynder-marketplace-connectors.bynder-compact-view.bynder-asset-model.bynder-derivatives.bynder-webhooks-events.contentful-content-model (entry shape), contentful-react-wrapper (front-end consumption), contentful-app-framework (the custom field control hosting).../../references/marketplace-connectors.md../../references/bynder-foundations.md../contentful/skills/contentful-app-framework/SKILL.md