Fix templates dropping all nested content (editor preview + published output) #8

Merged
jknapp merged 1 commits from fix-zone-preview into main 2026-07-13 13:28:39 +00:00
Owner

Root cause: TemplateModal.addTemplateComponents() built each template component via React.createElement(Component, comp.props) and never passed comp.children — so loading ANY template silently dropped all nested content (nav links, footer, section contents) from the editor state AND from published output. Fable surfaced it as empty header/footer zone previews; it was actually every template.

Fix: extract templates/apply-template.ts (recursively builds comp.children into the node tree) and route it through the shared buildNodeTree, which was moved into craft-tree.ts and repaired (two latent bugs: data.type must be a real component reference not a {resolvedName} object; synthesized SHELL_INNER needs data.name). Same repair also fixes a pre-existing latent no-op in the AI apply-response section-replace/insert paths. No component toHtml changed. 580 tests + a real template-export regression test.

🤖 Generated with Claude Code

Root cause: `TemplateModal.addTemplateComponents()` built each template component via `React.createElement(Component, comp.props)` and never passed `comp.children` — so loading ANY template silently dropped all nested content (nav links, footer, section contents) from the editor state AND from published output. Fable surfaced it as empty header/footer zone previews; it was actually every template. Fix: extract `templates/apply-template.ts` (recursively builds `comp.children` into the node tree) and route it through the shared `buildNodeTree`, which was moved into `craft-tree.ts` and repaired (two latent bugs: `data.type` must be a real component reference not a `{resolvedName}` object; synthesized SHELL_INNER needs `data.name`). Same repair also fixes a pre-existing latent no-op in the AI apply-response section-replace/insert paths. No component `toHtml` changed. 580 tests + a real template-export regression test. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
jknapp added 1 commit 2026-07-13 13:28:39 +00:00
TemplateModal's addTemplateComponents() built each template component via
React.createElement(Component, comp.props) without ever passing
comp.children, silently dropping every nested children array authored in
templates/definitions.ts (header/footer Container > Logo/Menu/TextBlock,
page Section > Heading/TextBlock/ButtonLink). The resulting Craft.js node had
nodes: [], so the header/footer zone preview (ZonePreview -> exportBodyHtml)
rendered as an empty strip, and published output was affected the same way.

Fix converts each TemplateComponent to a SerializedTreeNode and reuses
craft-tree.ts's buildNodeTree (sanitize -> flatten -> materialize) -- the
same tested tree pipeline already used for AI-generated content -- instead
of hand-rolling a React-element tree, since a naive nested-children fix via
parseReactElement crashes any component with an internal SHELL_INNER linked
canvas (Section/BackgroundSection/FormContainer) or linked columns
(ColumnLayout). Also fixes two latent bugs in buildNodeTree itself, only
surfaced by exercising it against a real Craft.js editor for the first time:
data.type must be the actual resolved component reference (not a string or
{resolvedName} object) for correct rendering, and the synthesized SHELL_INNER
node needs data.name set for actions.addNodeTree's own validation.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
jknapp merged commit 329a782052 into main 2026-07-13 13:28:39 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: cloud-hosting-platform/site-builder#8