Skip to content

Synthesized aside region carries className, which PageRegionSchema rejects — a Reference Rail page has no persistable spelling #4286

Description

@yinlianghui

Observation

buildDefaultPageSchema emits the Reference Rail's region as

{name: 'aside',width: 'small',className: 'hidden xl:flex flex-col gap-4',components: []}

PageRegionSchema (@objectstack/spec, packages/spec/src/ui/page.zod.ts) declares
name / width / components only, and it is closed under the same ADR-0089 D3a
.strict() flip as the page component shape. Parsing that region against the vendored
spec (17.0.0-rc.6) gives:

unrecognized_keys | <root> | Unrecognized key(s) on this page region: `className`.
Until #4001 closed this shape these were dropped silently — the page still rendered,
without whatever the key was meant to configure.

So a synthesized page that carries the Reference Rail has no spelling a server write
would accept.

Why this is filed as an observation, not a defect

It is not reachable from any persisted payload today. The only path that stores a
synthesized page is Studio's page-create seed
(packages/app-shell/src/views/metadata-admin/anchors.tscreateSeed), which calls
buildDefaultPageSchema(objectDef) with no options — so showReferenceRail is off,
slots.rightRail is empty, and the aside region is never emitted into the PUT. Every
other caller (RecordDetailView, PagePreview) renders the tree in the browser and
never writes it, where the region's className is honoured by RegionContent
(packages/components/src/renderers/layout/page.tsx) and everything works.

It is worth recording because it is the same defect class as #4232 (which fixed the
component-level half — props now go in the spec's properties carrier), and because the
day anything persists a page with the rail on, that write fails the same way page-create
did.

Why #4232 did not fix it

Unlike recordChrome / items, this key has no spec-shaped carrier. The options and
their costs, so whoever picks this up does not have to re-derive them:

  • Drop the className — loses the responsive hide (hidden xl:) and the rail's own
    flex flex-col gap-4 spacing. The rail would render at every width, taking a column
    from the main content on laptop widths, which is the layout the class exists to prevent.
  • Move it onto the child componentsPageComponentSchemadoes declare className
    and responsiveStyles, but the hide has to apply to the region wrapper: hiding the
    children leaves an empty column occupying its width below xl. The gap-4 between
    siblings is a container concern and has no per-child spelling at all.
  • Give PageRegionSchema a carrier (a className, or an ADR-0065 responsiveStyles
    at region level) — an objectstack-lane spec change, and the only option that keeps the
    semantics intact. Needs the usual "is there real business pull" read: today the only
    author of a region className is this synthesizer.

Evidence

Measured on objectui origin/main @ 49ae9f42d with the vendored @objectstack/spec
17.0.0-rc.6, by parsing buildDefaultPageSchema(def, { showReferenceRail: true, related: [ …2 lists ] })'s
aside region with PageRegionSchema.safeParse.

Related: #4232 (component-level half, fixed).


Generated by Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpm:on-hold

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions