Used data-editable="content" | Not a valid region type. Valid types: text, image, array, array-item, component, source. For the markdown body use data-editable="text" data-type="block" data-prop="@content". |
Put defaults in template || fallbacks instead of schema frontmatter | data-editable regions display the stored field value, not the rendered HTML. Empty-string/missing field + template fallback = production renders default, editor shows blank. Put default values in the collection schema (and in structure-value defaults for page-builder blocks), not {x || "Default"} fallbacks. Keep a ?.trim() || safety net for legacy entries, and backfill existing content files. |
Assumed a component registered in componentMap.ts would live-update in the editor | Registration only enables page-builder instantiation as a _type block. Inline live-editing still requires data-editable attributes on every rendered text/image field and data-editable="array" + array-item + nested text on every .map(). These are independent concerns. |
Used data-editable="source" with data-path / data-key for a shared-data field | The canonical pattern in CloudCannon's Astro integration is data-editable="text" (or image, array, …) with data-prop="@data[<key>]...", where <key> is registered in data_config in cloudcannon.config.yml. source has different semantics; @data[<key>] routes through the same channel as frontmatter edits. |
| Changed a schema default without backfilling existing content | data-editable shows the stored value. Existing entries keep the old (often empty) value; only brand-new entries get the new default. Always pair the schema change with a backfill script. |
Editing a static-placement section mutates a top-level frontmatter field instead of the nested key (e.g. heading instead of ctaBox.heading), or appears to do nothing | Component is registered in componentMap.ts and statically placed in a page/layout but is missing its <editable-component data-component="<name>" data-prop="<key>"> wrapper. A propPrefix-style prop is the wrong fix — it builds correct data-prop strings at compile time but the component never re-renders on field change. Wrap with <editable-component>; remove any propPrefix / scope() helper from the component. |
| Multiselect appears to work but selection is ignored — same output regardless of what's selected | Component has an if (length === 0) showAll fallback. Combined with a ref-comparison bug, the filtered array always empties and the fallback always fires. Remove the fallback. Empty array = render nothing. Seed defaults in .cloudcannon/schemas/<collection>.md. |
| Multiselect of refs renders nothing or renders all — selection appears not to work | reference() fields are {collection, id} objects at runtime, not strings. Comparing entry.id === ref is string-vs-object → always false → empty filter result. Use getEntry(ref) for one ref or entry.data.x.some(r => r.id === currentId) for membership. Type Props as {collection: string; id: string}[], never string[]. |
Component renders fine in astro build but a field is missing from Astro.props in the visual editor | The CC schema file (.cloudcannon/schemas/<collection>.md) gates which frontmatter fields are forwarded on re-render. Adding a hidden _input in cloudcannon.config.yml does NOT fix this — _inputs control sidebar UI, not prop forwarding. Add the missing key (with a sensible default) inside the correct nested object in the schema file. |