You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Console renders nav:menu / global:search / global:notifications / app:launcher as "Component Placeholder" — four spec-declared PageComponentType members with no renderer #12183
Four page-component types that @objectstack/spec declares as first-class, no-props members of PageComponentType have no renderer in the console: each one draws the literal scaffold text Component Placeholder with its own type name above it, on the page where an author placed it.
Measured in a real browser against a running app — not read off source. Downstream tracking card: objectstack-ai/hotcrm#734 (half 1).
Environment
@objectstack/*17.1.0 (every package in the app pinned to it; nothing bumped for the measurement)
App: HotCRM at objectstack-ai/hotcrm@f685136, served by objectstack dev -p 4001, seed data loaded on first boot
Browser: Chromium 1194 via Playwright, admin-authenticated as the seeded dev admin (admin@objectos.ai), viewport 1600×1200
Node 22.22.2, pnpm 10.33.0
Reproduction
Sign in to the console as an admin and open, in the published app:
All five component instances across the three pages draw the placeholder. Each is a dashed-outline box containing a document-with-question-mark glyph, the component type in monospace, and the caption Component Placeholder:
Page
Component
Renders
sales_home_page
nav:menu (inside the Quick Create card)
⛔ nav:menu / Component Placeholder
app_launcher_page
global:search
⛔ global:search / Component Placeholder
app_launcher_page
app:launcher
⛔ app:launcher / Component Placeholder
utility_bar_page
global:notifications
⛔ global:notifications / Component Placeholder
utility_bar_page
global:search
⛔ global:search / Component Placeholder
Occurrences of the literal string Component Placeholder in document.body.innerText: 1 on sales_home_page, 2 on app_launcher_page, 2 on utility_bar_page.
Verbatim innerText from the app_launcher_page main region:
Central hub for accessing all applications
global:search
Component Placeholder
App Launcher
Select an app to get started
app:launcher
Component Placeholder
and from utility_bar_page:
Utility Bar
Quick access utility bar with floating tools
global:notifications
Component Placeholder
Quick Notes
global:search
Component Placeholder
This is not a page-framework failure — the same pages render everything else correctly. On sales_home_page the four object-metric KPI cards pull real figures (Revenue (Won) 1,290,000.00 / Deals Won 8 / Pipeline Value 3,775,000.00 / Open Leads 21), the embedded list views return 21 / 10 / 6 real rows, and page:header draws. Only these four component types fall through to the placeholder.
Why this is a platform gap and not app metadata using a wrong spelling
All four are named members of the PageComponentType enum shipped in @objectstack/spec@17.1.0, and each has a deliberate no-props row in ComponentPropsMap:
where emptyProps builds a strict, intentionally empty props object whose own history string is explicit that the emptiness is the point:
varemptyProps=(type)=>strictObject({surface: `this \`${type}\` component`,history: `\`${type}\` declares no props at all. ${PROPS_HISTORY}`,guidanceSets: COMPONENT_LEVEL_GUIDANCE},{});
So the app is using the spec's sanctioned spelling, with the exact props shape the spec prescribes (properties: {}), and objectstack validate passes clean on all three pages. The metadata is right; the renderer is missing.
Impact
An end user who reaches any of these pages sees developer scaffolding. app_launcher_page and utility_bar_page are, between them, entirely placeholder plus one empty card — there is no non-scaffold content on either page. Any app that composes a launcher, a global search box, a notifications panel or a nav menu from the spec's own vocabulary gets the same result.
Ask
Either implement renderers for the four types, or — if they are not intended to be author-placeable on a page — make that explicit in the spec and in validate so the failure lands at author time rather than in front of a user. Shipping them as first-class enum members with prescribed props and no renderer is the state that produces this report.
⚠️ The downstream app metadata is deliberately being left untouched: these three pages are currently the only reproduction of this gap, so "fixing" them app-side would delete the evidence rather than the defect.
Adjacent but separate, and not part of this report: page:card components declaring a title and no body render as titled empty boxes (Quick Notes on utility_bar_page, Recent Items / Today's Schedule on sales_home_page). That is a container with nothing to draw, not a missing renderer.
Small spec-accuracy note while looking: PageComponentSchema.type is a z.ZodUnion<[z.ZodEnum<{…}>, z.ZodString]>, so despite being an enumerated vocabulary it accepts arbitrary strings at parse time. That is why an unimplemented type reaches the renderer as a plain string and lands on the placeholder branch rather than being rejected. It does not weaken anything above — the four names are declared members with declared props — but it is likely relevant to any fix that wants author-time rejection.
Four page-component types that
@objectstack/specdeclares as first-class, no-props members ofPageComponentTypehave no renderer in the console: each one draws the literal scaffold textComponent Placeholderwith its own type name above it, on the page where an author placed it.Measured in a real browser against a running app — not read off source. Downstream tracking card: objectstack-ai/hotcrm#734 (half 1).
Environment
@objectstack/*17.1.0 (every package in the app pinned to it; nothing bumped for the measurement)objectstack-ai/hotcrm@f685136, served byobjectstack dev -p 4001, seed data loaded on first bootadmin@objectos.ai), viewport 1600×1200Reproduction
Sign in to the console as an admin and open, in the published app:
What renders
All five component instances across the three pages draw the placeholder. Each is a dashed-outline box containing a document-with-question-mark glyph, the component type in monospace, and the caption
Component Placeholder:sales_home_pagenav:menu(inside the Quick Create card)nav:menu/Component Placeholderapp_launcher_pageglobal:searchglobal:search/Component Placeholderapp_launcher_pageapp:launcherapp:launcher/Component Placeholderutility_bar_pageglobal:notificationsglobal:notifications/Component Placeholderutility_bar_pageglobal:searchglobal:search/Component PlaceholderOccurrences of the literal string
Component Placeholderindocument.body.innerText: 1 onsales_home_page, 2 onapp_launcher_page, 2 onutility_bar_page.Verbatim
innerTextfrom theapp_launcher_pagemain region:and from
utility_bar_page:This is not a page-framework failure — the same pages render everything else correctly. On
sales_home_pagethe fourobject-metricKPI cards pull real figures (Revenue (Won) 1,290,000.00 / Deals Won 8 / Pipeline Value 3,775,000.00 / Open Leads 21), the embedded list views return 21 / 10 / 6 real rows, andpage:headerdraws. Only these four component types fall through to the placeholder.Why this is a platform gap and not app metadata using a wrong spelling
All four are named members of the
PageComponentTypeenum shipped in@objectstack/spec@17.1.0, and each has a deliberate no-props row inComponentPropsMap:dist/ui/index.d.ts:dist/ui/index.js:where
emptyPropsbuilds a strict, intentionally empty props object whose own history string is explicit that the emptiness is the point:So the app is using the spec's sanctioned spelling, with the exact props shape the spec prescribes (
properties: {}), andobjectstack validatepasses clean on all three pages. The metadata is right; the renderer is missing.Impact
An end user who reaches any of these pages sees developer scaffolding.
app_launcher_pageandutility_bar_pageare, between them, entirely placeholder plus one empty card — there is no non-scaffold content on either page. Any app that composes a launcher, a global search box, a notifications panel or a nav menu from the spec's own vocabulary gets the same result.Ask
Either implement renderers for the four types, or — if they are not intended to be author-placeable on a page — make that explicit in the spec and in
validateso the failure lands at author time rather than in front of a user. Shipping them as first-class enum members with prescribed props and no renderer is the state that produces this report.Notes for whoever picks this up
page:cardcomponents declaring atitleand nobodyrender as titled empty boxes (Quick Notesonutility_bar_page,Recent Items/Today's Scheduleonsales_home_page). That is a container with nothing to draw, not a missing renderer.PageComponentSchema.typeis az.ZodUnion<[z.ZodEnum<{…}>, z.ZodString]>, so despite being an enumerated vocabulary it accepts arbitrary strings at parse time. That is why an unimplemented type reaches the renderer as a plain string and lands on the placeholder branch rather than being rejected. It does not weaken anything above — the four names are declared members with declared props — but it is likely relevant to any fix that wants author-time rejection.