docs(react-pages): state the html tier's registered-name rule and scope the PascalCase one - #13734
Merged
Merged
Conversation
…pe the PascalCase one The html tier's allowed tags are the registry's own type names: `compile()` in `@objectstack/sdui-parser` builds its whitelist as `Object.keys(manifest.components)` and `parse.ts` matches the tag against it by exact string, with no case folding. All 57 keys in `sdui.manifest.json` are lowercase — `list-view` is there, `ListView` is not — so a PascalCase tag borrowed from the react tier is rejected at save time with "is not an allowed component". The page never said so. Its PascalCase sentence was unqualified while the page is also the documentation home for the html tier, so an author reading top to bottom had no way to learn the naming rule before hitting the error. Two body edits, no restructuring: - the html-tier section now names the registered spelling, including the namespaced and layout forms, and names the error a borrowed PascalCase tag produces; - the react-tier sentence is scoped to that tier and points at the html spelling. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Pk26oZ12t5N1hwGW1m1MgC
This was referenced Aug 31, 2026
os-project-manager
marked this pull request as ready for review
August 31, 2026 09:09
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 #12650
What was wrong
content/docs/ui/react-pages.mdxis the documentation home for both source-authoringtiers —
content/docs/ui/pages.mdxsends the html-tier reader here for "thehtmlandreactsource-authoring tiers in full" — but everything from the security-gate sectiondown is react-tier material carrying no tier marker. The naming sentence was unqualified:
So an author who reads the page top to bottom and then writes a
kind:'html'page copiesListView, is rejected at save time with "is not an allowed component", and finds nothingon the page naming the rule they broke. The html-tier section already said "only tags in
the public block manifest are accepted" and "an unknown tag is a hard error at save time"
without ever saying how those tags are spelled — that is the exact gap.
Evidence from the registration code
The html tier's whitelist is the registry's own type names, compared by exact string:
packages/sdui-parser/src/index.ts—compile()buildsconst allowedTags = new Set(Object.keys(manifest.components)).packages/sdui-parser/src/index.ts—manifestFromConfigs()keys the manifest by theregistry config's own
type:components[c.type] = { type: c.type, ... }.packages/sdui-parser/src/parse.ts:61— the check is!this.opts.allowedTags.has(tag). An exactSet.has; there is no case foldinganywhere in the parser, and the parsed node keeps
type: tagverbatim.sdui.manifest.json(objectui's registry-inputs dump, 57 components) — zero keysbegin with an uppercase letter.
list-viewpresent,ListViewabsent;object-formpresent,
ObjectFormabsent.packages/spec/src/ui/react-blocks.ts—ReactBlockDef.tagis documented as "PascalCasename the author writes in JSX" and
schemaTypeas "The registry/render type, e.g.object-form". PascalCase is a react-tier projection, not a registered name.Compiled against that real manifest (
compile(source, sdui.manifest.json)):ListViewListView is not an allowed componentlist-viewObjectFormObjectForm is not an allowed componentobject-formRecordRelatedListRecordRelatedList is not an allowed componentrecord:related_listflexOne correction to the card's wording
"kebab-case" is the shape of the plain block names but not the whole rule: 28 of the 57
registered names carry a namespace prefix (
record:,page:,element:,action:), andfour are snake_case after the colon —
record:related_list,record:line_items,record:quick_actions,record:reference_rail. Writing only "kebab-case" would have sentan author to
record:related-list, which is not registered either. The page therefore saysregistered type names, written verbatim, with kebab-case named as the shape and a
namespaced example shown.
The change
Two body edits, no restructuring of either tier section:
plain, namespaced and layout-container examples) and naming the error a borrowed
PascalCase tag produces.
spelling.
Headings, frontmatter and every table are untouched — this stays clear of epic #12243's
content/docs/**frontmatter/headings slice.Verification
pnpm check:doc-anchors,check:doc-authoring,check:docs-single-h1,check:doc-frontmatter,check:react-page-adapter-contractand the rest of the derivedfamily: 25 GREEN, 0 RED, 1 NOT MEASURED, run at
6c5a1a754(the final commit). The26-family list came from
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstackre-derived after the commit; NOT MEASURED is
scripts/check-test-completeness.mjs, whichprints "PREREQUISITE NOT MET" because it grades a saved
turbo run testlog that no localrun produced — its own text says to record it as NOT MEASURED locally.
check:nul-bytesgreen (7572 files); the edited file also scanned directly for raw ASCIIcontrol bytes, none found. The MDX itself compiles (
@mdx-js/mdxcompile()on the editedfile, frontmatter stripped, output 33002 chars) — worth checking because the added text puts
tag names with angle brackets and a colon inside inline code spans.
Declared narrowing — repo-wide ESLint.
pnpm lintwas not run whole. Measured instead:eslint --no-inline-config --format json content/docs/ui/react-pages.mdxreports 1 entry,0 errors, and its single message is "File ignored because no matching configuration was
supplied" — the population comes from ESLint's own config, not my guess, so this
.mdxpath is outside the linted set entirely. The diff touches that one file and no ESLint
config, and no type-aware linting is involved, so no untouched file's verdict can move.
Not addressed here
Docs-only, so no changeset — the diff publishes nothing from any package, and the
skip-changesetlabel carries that (recentcontent/docs/**-only merges land the sameway). objectstack-ai/objectui#6598, the html-tier
columnsbinding defect from the samerecon, is out of scope: this documents naming only and papers over nothing.
Generated by Claude Code