Wednesday, 24 June 2026

Why Sitecore Placeholder Children Fail with “Missing from component-map.client” in Next.js App Router

 If you’ve ever dropped a perfectly valid Sitecore rendering into a nested <Placeholder> and watched Pages Builder (or your local app) complain that it can’t find the component in component-map.client, you’re not alone — and you’re probably not looking in the wrong place.

This post walks through a real debugging session from an XM Cloud / Sitecore Content SDK Next.js App Router site: adding a Video rendering inside an Interior Media Hero Banner placeholder. The component existed. The GraphQL query existed. The Sitecore rendering componentName was set. And yet the client still couldn’t resolve it.

The root cause wasn’t placeholder naming. It was architecture.




The symptom

We needed an optional video slot inside an interior hero banner. The Sitecore wrapper rendered a dynamic placeholder roughly like:



Authors could insert a Video rendering into that slot. On the frontend, resolution failed with an error implying the component was missing from the client component map.

That wording matters. It didn’t say “Video is not registered.” It pointed specifically at component-map.client.

The wrong first instincts (and why they’re reasonable)

Before finding the real issue, it’s easy to chase:

  • Placeholder name mismatch — interior-media-{DynamicPlaceholderId} vs Sitecore Placeholder Settings
  • Missing Placeholder Settings / dynamic placeholder flags on the parent rendering
  • Wrong componentName on the Video JSON/YAML
  • Component map not regenerated after adding files
  • Video GraphQL/datasource issues
  • Those can all be real problems. In our case, they weren’t the ones throwing the client-map error.


A useful clue: the same placeholder pattern already worked elsewhere in the project for Resource Promo, which nests child renderings into named placeholders. So placeholders themselves weren’t broken.


The architecture that actually matters

In this Next.js App Router setup, there are (at least) two maps:


Map Typical file Used for
Full / server map .sitecore/component-map.ts App layout resolution, broader server rendering
Client map .sitecore/component-map.client.ts What SitecoreProvider hands to client-side placeholder resolution


The app provider looked essentially like this:


That means when you use the Content SDK’s <Placeholder> component, nested renderings are resolved against component-map.client.ts, not the full server map.


Meanwhile, Layout / AppPlaceholder patterns can still use the fuller component-map.ts.


So you can have:

  • Video registered in component-map.ts 
  • Video missing from component-map.client.ts 
  • Nested <Placeholder> fails 

That’s the trap.


Why is the client map smaller?

In this codebase, component-map.client.ts is generated/populated with components considered client-safe — generally Sitecore wrappers that include:


Important nuance:

Making the UI component a client component does not automatically put the Sitecore wrapper on the client component map.


Sitecore resolves by rendering componentName → wrapper export in the map. The map generation cares about the Sitecore wrapper module’s client boundary, not whether some child React tree eventually needs hooks.


Two valid fixes

Option A — Make the nested rendering a client Sitecore wrapper (common for interactive widgets)

  1. Add "use client"; to the Sitecore wrapper (Video.tsx)
  2. Regenerate maps (sitecore-tools:generate-map / sitecore-tools:build depending on your pipeline)
  3. Confirm Video appears in .sitecore/component-map.client.ts
  4. Confirm related symbols appear in .sitecore/import-map.client.ts if your setup uses import maps

Choose this when:

  • the component is interactive (modals, players, state)
  • you intentionally want it available anywhere <Placeholder> resolves client-side
  • editing/preview chrome depends on client hydration for that nested branch

Option B — Resolve with AppPlaceholder + the server map (Container-style)

Some wrappers already do this:



Choose this when:

  • you want to keep the child wrapper as a server component
  • the parent already has page and can supply the full map
  • you’re mirroring an established container pattern in the repo

Neither fix is “more correct” universally. They’re different seams in the same architecture.

Authoring checklist (related, but separate)

Even after the map issue is fixed, dynamic placeholders still need Sitecore-side wiring:

  1. Placeholder Settings with a key like interior-media-{*}
  2. Parent rendering flags such as IsRenderingsWithDynamicPlaceholders=true
  3. Parent rendering Placeholders field linking those settings
  4. Child rendering componentName matching the map key (Video, InteriorMediaHeroBanner, etc. — avoid accidental spaces like Interior Media Hero Banner if the map key is PascalCase)

Those issues usually show up as empty slots or authoring constraints. The client-map error is the giveaway that resolution never found the React module on the map your provider uses.


A practical debugging checklist for the future

When a nested rendering fails with a client-map message:

  1. Search both maps for the componentName
  2. If present only in component-map.ts, you’ve found the mismatch
  3. Check whether the Sitecore wrapper has "use client"
  4. Compare with a working nested child in the same repo
  5. Decide: promote wrapper to client or resolve via server AppPlaceholder
  6. Rebuild Sitecore maps and retest in normal + editing modes

Don’t start by rewriting GraphQL until the map lookup succeeds.


Takeaway

In Sitecore Content SDK App Router apps, placeholder resolution is only as capable as the component map you hand to SitecoreProvider.

If that map is the client map, then every nested rendering must be client-map eligible — usually by being a client Sitecore wrapper — unless you deliberately resolve that slot with the fuller server map.

The Video-in-hero failure wasn’t mysterious once we asked one question:


Which map is this Placeholder using — and is my child actually on it?


That question will save you hours.


Helpful resources

Sitecore / XM Cloud / Content SDK

Next.js App Router / client boundaries

No comments:

Post a Comment