fix(publisher): render current entry body in any content outlet#62
Merged
Conversation
A base.outlet only rendered the post body when the node carried a persisted dynamicBindings.html overlay, which was set in exactly one place: the auto-seeded default template. A hand-dropped outlet (custom template) had no binding, so the publisher filled it with nothing and it rendered as an empty <main data-instatic-content-region></main> — on the published page, the content preview, and the Live Canvas alike. An outlet is, by definition, the hole the current entry's body flows into; there is no UI to bind it and the binding is always the same. Apply it implicitly via effectiveNodeBindings() at the shared resolution layer so every outlet renders the body, and drop the now-redundant persisted binding from the seed (single source of truth). Outside an entry route the entry stack is empty, so the binding stays inert and an everywhere layout's outlet still hosts a whole page. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
A
base.outletonly rendered the current entry's body when the node carried a persisteddynamicBindings.htmloverlay — which was set in exactly one place: the auto-seeded default entry template (buildDefaultTemplateCells).When a site owner builds their own post template and drags a Content Outlet in by hand, that outlet has
props.html: ''and no binding, so the publisher filled it with nothing and it rendered as an empty<main data-instatic-content-region></main>.The body resolution (
resolveDynamicProps) is shared by all three render surfaces, so the gap broke the published page, the content preview API, and the Live Canvas editor alike.Why
An outlet is, by definition, the hole the current entry's body flows into — there is no UI to bind it and the binding is always the same (
currentEntry.body, rendered markdown → HTML). Relying on a persisted overlay that only the seeder set was fragile: any hand-authored outlet was silently broken.The fix
dynamicBindings.ts— neweffectiveNodeBindings(node)helper applies thecurrentEntry.body → htmlbinding implicitly to everybase.outlet, merged on top of any persisted overlay.renderNode.ts(publisher) andNodeRenderer.tsx(editor canvas) now resolve througheffectiveNodeBindings(node)so all surfaces behave identically.templateSeeding.ts— dropped the now-redundant persisted binding from the seed; a seeded outlet is now identical to a hand-dropped one (single source of truth).Outside an entry route the entry stack is empty, so the binding resolves to nothing and the outlet stays empty — an
everywherelayout's outlet still hosts a whole page.User / developer impact
Dragging a Content Outlet into a custom post template now renders each post's body in it — on the canvas, in the live editor, and on the published page. No migration needed; existing seeded templates keep working (the implicit binding resolves to the same value).
Verification
src/__tests__/publisher/outletEntryBody.test.tsreproduces the bug (outlet with no persisted binding) and confirms the body renders, plus the inert-outside-entry-routes case.bun test src/__tests__/publisher/ src/core/templates/ server/publish/→ 405 pass.bun run buildandbun run lint→ clean.react-doctor --scope changed --base main→ no new issues.🤖 Generated with Claude Code