Repository navigation
fix(app-shell): Studio's page previews draw the page's own kind, as the running app does (objectui#11933) - #11959
Merged
objectstack-fleet[bot] merged 5 commits intoOct 8, 2026
Conversation
…d (objectui#11933)
Studio's source-page preview wrote the page's kind into the node `type`
only. PageRenderer reads the kind from `pageType`, so every source page
previewed as a record page: record width, no title heading. The running
app's PageView wrote both keys.
Both writers now spread one module-private builder, `pageKindNode`, for
the `{ type, pageType }` pair, so they cannot drift again. PageView's
output is unchanged; data and context wiring stay with each writer.
Pin: SourcePageEditor.pageKind-11933 renders through the real
SchemaRenderer and PageRenderer: an app and a home page preview with the
title heading and a non-record width; a record page previews as the
renderer's record default, as before.
Claude-Session: https://claude.ai/code/session_01MgfduSkFrfM3eorB3UGfAU
Co-authored-by: Claude <noreply@anthropic.com>
…offline (objectui#11933) The preview half never mounts the editor, but the component asks the Monaco loader either way; the sibling source-page tests mock it offline, and so does this pin, so no CDN script is requested. Claude-Session: https://claude.ai/code/session_01MgfduSkFrfM3eorB3UGfAU Co-authored-by: Claude <noreply@anthropic.com>
…ly (objectui#11933) Claude-Session: https://claude.ai/code/session_01MgfduSkFrfM3eorB3UGfAU Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MgfduSkFrfM3eorB3UGfAU Co-authored-by: Claude <noreply@anthropic.com>
…nd too (objectui#11933)
PagePreview's run-mode render handed SchemaRenderer `{ ...draft, type }`
with no `pageType`, so an app or home region page drew as a record page:
record width, no title heading. Its `schema` memo now spreads the same
`pageKindNode` builder PageView and the source-page preview use.
The empty-draft check counted the memo's keys (`<= 1`), which the new
`pageType` key would have moved; it now asks the draft's own keys, a
`type` aside, which is the same predicate the old count expressed.
Pin: PagePreview.pageKind-11933 renders through the real PageRenderer:
app and home draw the title and a non-record width; a record page draws
as the untyped record default; an empty draft, typed or not, still shows
the add-components message. Changeset and the builder's comments name
both previews.
Claude-Session: https://claude.ai/code/session_01MgfduSkFrfM3eorB3UGfAU
Co-authored-by: Claude <noreply@anthropic.com>
Contributor
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
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.
Fixes #11933
Clause-②: no
Surface amended by the seat:
PagePreview.tsx(card Done-when bullet 1)What was wrong
A page's KIND (
app,home,record,utility) rides two keys on the node handed toSchemaRenderer: the nodetypethatComponentRegistrydispatches on, and a copy onpageType, whichPageRendererreads for the page's max-width, itsdata-page-typeand whether it draws the implicit title heading. The running app'sPageViewwrote both. Studio's two page previews wrotetypeonly:html/reactpage's source (SourcePageEditor,previewSchema);PagePreview, itsschemamemo).So
PageRendererfell back torecordand anapporhomepage previewed at the record width with no title heading, while the running app drew both. That breaks the previews' contract, quoted fromSourcePageEditor's header: "a live preview rendered through the runtime SchemaRenderer".The change
pageKindNodebesidePageView(packages/app-shell/src/views/pageKindNode.ts). It returns{ type: page.type || 'page', pageType: page.type }, which is exactly the pairPageViewwrote inline. It is not exported from the package entry.PageView,SourcePageEditorandPagePreviewall spread it, so the three writers cannot drift again.PageView's output is unchanged.PageView'scontext: { params }and its two providers stay with that writer, because a preview has no URL.PagePreviewneeded one more line. Its empty-draft check counted the memo's keys (at most one key meant empty), and the builder'spageTypekey would have moved that count. It now asks the draft's own keys, withtypeset aside. That is the same predicate the old count expressed. The second ablation leg below shows the line is load-bearing.Hypothesis reading (H1): the preview dropped exactly one page-shape key,
pageType. It also used a different fallback operator (??wherePageViewuses||), which differs only for an empty-stringtype. The title heading and the width class are not separate keys.PageRendererderives both frompageType(getPageMaxWidth, andheaderOwnsTitlereadingpageType === 'record'), and the title text istitle ?? label, which every writer carries through the spread.Pins (real
SchemaRenderer, realComponentRegistry, realPageRenderer)Widths are compared, never hard-coded. The classes are
PageRenderer's choice; this card owns only that a non-record page does not get the record width.SourcePageEditor.pageKind-11933.test.tsx(preview half; only the Monaco loader is mocked offline, as in the sibling source-page tests):recordpage draws exactly as an untyped page does. That is the renderer's record default: no h1, same width.appandhomedrawdata-page-typeequal to the kind, the title heading, and a width that is not the record width.PageTypeSchemareaches the renderer as itself.PagePreview.pageKind-11933.test.tsx(Run-mode render, no design mode):recordCONTROL, and the sameapp/homecases.page-kind-writing-end-9718still pinsPageView's write, kind by kind, and is unchanged and green. Card bullet 3: it is not widened. Each preview's write is pinned at render level beside that preview, and all three writers spread one builder.Ablations (fix committed first;
ablation-replace.mjs, which verifies on disk and restores to HEAD)SourcePageEditor, run at36b3d33fb. The pre-fixtype-only line was restored: anchor x1 to x0, blob90ef1c7fa03eto268b032164fd. Result:Tests 3 failed | 1 passed (4). Forappandhomethe pin expected the kind and receivedrecord; the record CONTROL stayed green. The restore matched the HEAD blob andgit diff HEADwas empty.PagePreview, run at811475cd3:type-only memo was restored (blobb29ef4ae1128to5da520728ac5). Result:Tests 2 failed | 3 passed (5). Forappandhomethe pin expected the kind and receivedrecord.b29ef4ae1128to13ca9d01052d). Result:Tests 2 failed | 3 passed (5). Both empty-draft CONTROLs went red.b29ef4ae1128withgit diff HEADempty.Gates, at HEAD
811475cd3(git rev-parse --short HEADafter the last commit;mainmerged at1c51e973b, no conflicts)pnpm exec vitest run:page-kind-writing-end-9718, and the fivePageView.*tests;no-refresh-key-remount.ratchet,useMonacoFallback.loaderRejection-11800andResourceEditPage.pageRequiresStamp-11357;dataPreviews.i18n-10862-s3,PagePreview.test,PagePreview.expandFls-7429andpage-preview-record-type-10482;StudioDesignSurfacetests that mountPagePreview:interfacesReadOnly-11136,autosaveInFlight-11204,autosaveSwitch-11232,navItemTypes-11790andnavPlaceholderSave-11776;packages/corecolumn-identity.ratchet, and the twoscripts/__tests__files that readPageView's source.Test Files 23 passed (23),Tests 223 passed (223), lockVERDICT command-exit 0.pnpm --filter @object-ui/app-shell type-check(tsc --noEmit && tsc -p tsconfig.test.json) gaveVERDICT command-exit 0. It ran after rebuilding the dependency closure, and@object-ui/plugin-listagain after the merge.--listFilesOnlyshows both pins and the builder in the test program.PageViewhas 3 against 5 onmain, andPagePreviewhas 15 against 15 onmain, all pre-existingno-explicit-any/set-state-in-effect. Type-aware linting is off ineslint.config.js, so the diff moves no verdict on an untouched file. Repo-widepnpm lintis left to CI.check:unreferenced-sources: "OK Every shipped source file in every covered package is reachable."check-changeset-presence: "6 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s)".check-changeset-no-major,check:changeset-claimsandcheck:pending-changeset-literals: green.check:new-line-citations: "VERDICT new-cross-file-line-citations: 0 new citation(s)".check:spec-symbols,check:control-bytes,check:vi-mock-specifiers/-inherit/-override-shapeandcheck:test-path-roots: all exit 0.PageView's closure, and the inline pair it replaces removed.Changeset and docs
.changeset/11933-preview-page-kind.md: apatchfor@object-ui/app-shell. Nothing is added to the package entry.Session:
https://claude.ai/code/session_01MgfduSkFrfM3eorB3UGfAUGenerated by Claude Code