Skip to content

fix(spec): make dashboard widget layout optional (auto-flowed when omitted)#2247

Merged
os-zhuang merged 1 commit into
mainfrom
fix/dashboard-widget-layout-optional
Jun 23, 2026
Merged

fix(spec): make dashboard widget layout optional (auto-flowed when omitted)#2247
os-zhuang merged 1 commit into
mainfrom
fix/dashboard-widget-layout-optional

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Problem

Found by dogfooding the Studio dashboard designer in the browser: you could not save or publish any dashboard authored in the designer.

DashboardWidgetSchema.layout was required, but the entire runtime treats it as optional:

  • objectui's DashboardGridLayout auto-flows any widget without a layout (x: (i%4)*3, y: ⌊i/4⌋*4, w: 3, h: 4).
  • The Studio dashboard designer's addWidget creates widgets without a layout by design.

So every designer-authored dashboard failed spec validation the moment a widget was added — the draft PUT /api/v1/meta/dashboard/<name>?mode=draft returned 422 (widgets: Invalid type: expected object, received undefined), the draft never saved (stuck "Unsaved"), and Publish stayed disabled — even though the widget rendered correctly in the canvas.

Fix

Make layout optional; absence means "auto-place". Authors may still pin an explicit grid position.

  • Backward-compatible — existing dashboards that specify layout are unaffected.
  • Adds 2 regression tests (a layout-less widget and a designer-authored layout-less dashboard must validate).
  • Adds a changeset.

Verification

  • 804/804 spec UI tests pass.
  • End-to-end on a patched server: the same layout-less draft now returns 200, Publish enables, and a 10-widget dashboard publishes.

Pairs with objectui fix(dashboard): auto-flow layout-less widgets in the positioned grid so layout-less dashboards also render as a clean grid.

🤖 Generated with Claude Code

…omitted)

`DashboardWidgetSchema.layout` was required, but the entire runtime treats it
as optional: objectui's DashboardGridLayout auto-flows any widget without a
layout, and the Studio dashboard designer adds widgets WITHOUT a layout by
design.

The mismatch meant every dashboard authored in the Studio designer failed spec
validation the moment a widget was added — the draft PUT /meta/dashboard/...
returned 422 ("widgets: Invalid type: expected object, received undefined"), so
the draft never saved and Publish stayed disabled, even though the widget
rendered. Found by dogfooding the dashboard designer in the browser; verified
the fix end-to-end (422 -> 200, Publish enabled, 10-widget dashboard published).

layout is now optional; absence means "auto-place". Backward-compatible —
existing dashboards that specify layout are unaffected. Adds two regression
tests + a changeset.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 23, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
spec Building Building Preview, Comment Jun 23, 2026 5:43pm

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation tests protocol:ui tooling size/s labels Jun 23, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/spec.

91 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/concepts/architecture.mdx (via @objectstack/spec)
  • content/docs/concepts/cloud-artifact-api.mdx (via packages/spec)
  • content/docs/concepts/cluster-semantics.mdx (via @objectstack/spec)
  • content/docs/concepts/design-principles.mdx (via packages/spec)
  • content/docs/concepts/implementation-status.mdx (via @objectstack/spec)
  • content/docs/concepts/index.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-driven.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-lifecycle.mdx (via packages/spec)
  • content/docs/concepts/north-star.mdx (via packages/spec)
  • content/docs/concepts/packages.mdx (via @objectstack/spec)
  • content/docs/concepts/setup-app.mdx (via @objectstack/spec)
  • content/docs/concepts/skills.mdx (via @objectstack/spec)
  • content/docs/concepts/webhook-delivery.mdx (via @objectstack/spec)
  • content/docs/getting-started/architecture.mdx (via @objectstack/spec)
  • content/docs/getting-started/cli.mdx (via @objectstack/spec)
  • content/docs/getting-started/core-concepts.mdx (via @objectstack/spec)
  • content/docs/getting-started/examples.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-start.mdx (via @objectstack/spec)
  • content/docs/guides/adding-a-metadata-type.mdx (via @objectstack/spec)
  • content/docs/guides/ai-capabilities.mdx (via @objectstack/spec)
  • content/docs/guides/airtable-dashboard-analysis.mdx (via @objectstack/spec)
  • content/docs/guides/analytics-datasets.mdx (via @objectstack/spec)
  • content/docs/guides/api-reference.mdx (via @objectstack/spec)
  • content/docs/guides/business-logic.mdx (via @objectstack/spec)
  • content/docs/guides/cheatsheets/backward-compatibility.mdx (via @objectstack/spec)
  • content/docs/guides/cheatsheets/error-catalog.mdx (via @objectstack/spec)
  • content/docs/guides/cheatsheets/field-type-gallery.mdx (via @objectstack/spec)
  • content/docs/guides/cheatsheets/field-validation-rules.mdx (via @objectstack/spec)
  • content/docs/guides/cheatsheets/permissions-matrix.mdx (via @objectstack/spec)
  • content/docs/guides/cheatsheets/protocol-diagram.mdx (via packages/spec)
  • content/docs/guides/cheatsheets/query-cheat-sheet.mdx (via @objectstack/spec)
  • content/docs/guides/cheatsheets/quick-reference.mdx (via @objectstack/spec)
  • content/docs/guides/client-sdk.mdx (via @objectstack/spec)
  • content/docs/guides/common-patterns.mdx (via @objectstack/spec)
  • content/docs/guides/contracts/auth-service.mdx (via packages/spec)
  • content/docs/guides/contracts/cache-service.mdx (via packages/spec)
  • content/docs/guides/contracts/data-engine.mdx (via @objectstack/spec)
  • content/docs/guides/contracts/index.mdx (via @objectstack/spec)
  • content/docs/guides/contracts/metadata-service.mdx (via packages/spec)
  • content/docs/guides/contracts/storage-service.mdx (via packages/spec)
  • content/docs/guides/data-modeling.mdx (via @objectstack/spec)
  • content/docs/guides/deployment-vercel.mdx (via @objectstack/spec)
  • content/docs/guides/driver-configuration.mdx (via @objectstack/spec)
  • content/docs/guides/error-handling-client.mdx (via @objectstack/spec)
  • content/docs/guides/error-handling-server.mdx (via @objectstack/spec)
  • content/docs/guides/external-datasources.mdx (via @objectstack/spec)
  • content/docs/guides/formula.mdx (via @objectstack/spec)
  • content/docs/guides/hook-bodies.mdx (via packages/spec)
  • content/docs/guides/kernel-services.mdx (via @objectstack/spec)
  • content/docs/guides/metadata/dashboard.mdx (via @objectstack/spec)
  • content/docs/guides/metadata/field.mdx (via @objectstack/spec)
  • content/docs/guides/metadata/flow.mdx (via @objectstack/spec)
  • content/docs/guides/metadata/index.mdx (via @objectstack/spec)
  • content/docs/guides/metadata/object.mdx (via @objectstack/spec)
  • content/docs/guides/metadata/validation.mdx (via @objectstack/spec)
  • content/docs/guides/metadata/workflow.mdx (via @objectstack/spec)
  • content/docs/guides/packages.mdx (via @objectstack/spec)
  • content/docs/guides/plugin-development.mdx (via @objectstack/spec)
  • content/docs/guides/plugins.mdx (via @objectstack/spec)
  • content/docs/guides/project-scoping.mdx (via @objectstack/spec)
  • content/docs/guides/public-forms.mdx (via @objectstack/spec)
  • content/docs/guides/runtime-services/email-service.mdx (via packages/spec)
  • content/docs/guides/runtime-services/index.mdx (via packages/spec)
  • content/docs/guides/runtime-services/queue-service.mdx (via packages/spec)
  • content/docs/guides/runtime-services/sharing-service.mdx (via packages/spec)
  • content/docs/guides/runtime-services/storage-service.mdx (via packages/spec)
  • content/docs/guides/security.mdx (via @objectstack/spec)
  • content/docs/guides/seed-data.mdx (via @objectstack/spec)
  • content/docs/guides/skills.mdx (via @objectstack/spec)
  • content/docs/guides/standards.mdx (via @objectstack/spec)
  • content/docs/guides/troubleshooting.mdx (via @objectstack/spec)
  • content/docs/guides/validating-metadata.mdx (via @objectstack/spec)
  • content/docs/protocol/knowledge.mdx (via @objectstack/spec)
  • content/docs/protocol/objectos/config-resolution.mdx (via @objectstack/spec)
  • content/docs/protocol/objectos/i18n-standard.mdx (via @objectstack/spec)
  • content/docs/protocol/objectos/lifecycle.mdx (via @objectstack/spec)
  • content/docs/protocol/objectos/plugin-spec.mdx (via @objectstack/spec)
  • content/docs/protocol/objectos/runtime-capabilities.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/index.mdx (via packages/spec)
  • content/docs/protocol/objectql/query-syntax.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/schema.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/security.mdx (via packages/spec)
  • content/docs/protocol/objectql/state-machine.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/actions.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/concept.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/index.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/layout-dsl.mdx (via packages/spec)
  • content/docs/protocol/objectui/record-alert.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/widget-contract.mdx (via @objectstack/spec)
  • content/docs/releases/index.mdx (via @objectstack/spec)
  • content/docs/releases/v9.mdx (via @objectstack/spec)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@os-zhuang
os-zhuang merged commit 6fbe91f into main Jun 23, 2026
15 of 16 checks passed
@os-zhuang
os-zhuang deleted the fix/dashboard-widget-layout-optional branch June 23, 2026 17:44
os-zhuang added a commit that referenced this pull request Jun 24, 2026
…hes (#2260)

Golden regression for the P1 found dogfooding the Studio dashboard designer:
the designer's addWidget creates widgets WITHOUT a `layout`, but the spec
required it, so every designer-authored dashboard returned 422 on draft save
and Publish stayed disabled — yet it passed every static gate because
code-authored example dashboards always specify a layout.

Boots the real showcase stack and drives the actual create -> save -> publish
metadata path with a layout-less, designer-shaped dashboard:
  - PUT /meta/dashboard/:name?mode=draft  -> 200 (was 422)
  - POST /meta/dashboard/:name/publish    -> 200
  - GET  /meta/dashboard/:name            -> widgets persisted, layout-less

Closes the "renders at design time != persists" coverage gap that hid the bug.
Pairs with the spec fix (#2247) that made DashboardWidget.layout optional.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation protocol:ui size/s tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant