## Summary
Vertical-list widgets can now omit `position` and use array order, with
an optional top-level `heightBehavior`. For example, `heightBehavior:
'TAB_VIEWPORT'` makes a widget fill the tab without repeating the tab
mode or an index.
Existing Canvas tabs, explicit widget indices, and nested height
settings keep their behavior. SDK validation warns about deprecated
shapes and explains the replacement; it does not rewrite manifests.
Shared validation also checks the new height setting and viewport
ordering before installation.
Existing apps keep their published SDK syntax. This PR updates the local
SDK fixture and current API documentation; app migrations can follow
after the SDK is published.
Stack 3/4, following the CI prerequisite and runtime height support. The
final PR migrates eligible stored Canvas tabs.
Review and merge order:
1. [App CI repairs](https://github.com/twentyhq/twenty/pull/25531)
2. [Widget height
behavior](https://github.com/twentyhq/twenty/pull/25512)
3. [Manifest authoring](https://github.com/twentyhq/twenty/pull/25513)
4. [Existing Canvas data
migration](https://github.com/twentyhq/twenty/pull/25511)
<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/25513?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->
`twenty-ui` uses an independent `1.0.0-alpha.2` version while the SDK
packages use `2.40.0`. Align UI with the SDK packages and add the shared
`set-local-version` target.
New apps pin `twenty-ui`, `twenty-sdk`, and `twenty-client-sdk` to the
scaffolder's version. The local-registry E2E workflow publishes UI
alongside the SDK packages and checks all three dependency versions.
Source docs and Codex plugin references describe the same policy, with a
validator regression test that catches independent UI version guidance.
This replaces the separate-alpha version pins from #25738 while
preserving its explicit inclusion of the MIT `LICENSE` in the npm
package. Plugin checklist rows touched: R3 (front component guidance)
and R5 (app concepts reference).
Companion: https://github.com/twentyhq/twenty-infra/pull/934 adds UI to
SDK publishing, automatic version bumps, and release notes. Land both
changes before the next version bump or SDK publication.
Validation: 11 scaffolding tests and 35 plugin tests passed; plugin
validation and direct typechecks for `twenty-ui` and `create-twenty-app`
passed. An npm pack dry run confirmed the MIT `LICENSE` is included. The
full registry/server E2E workflow was not run locally.
Fixes#25722.
## Problem
#23564 (merged 2026-07-30) relicensed the app-development packages to
MIT, but npm still serves builds that predate the relicensing:
- twenty-ui@1.0.0-alpha.0 (latest) and 1.0.0-alpha.1 (alpha tag, both
published 2026-06-24): AGPL-3.0 on the registry, old root LICENSE in the
tarball.
- twenty-shared@0.41.0-canary (published 2025-01-24): AGPL-3.0.
Meanwhile twenty-sdk, twenty-client-sdk, and create-twenty-app (all
published after 2026-07-30) are correctly MIT. The repo itself is
already correct (license: MIT plus per-package MIT LICENSE).
In practice, create-twenty-app scaffolds apps pinning "twenty-ui":
"1.0.0-alpha.1" and the generated front component imports from
twenty-ui/data-display and twenty-ui/icon — the exact scenario #23564
was written to prevent.
## What this PR does
- Bumps packages/twenty-ui/package.json 1.0.0-alpha.1 to 1.0.0-alpha.2
so the next publish ships the post-#23564 package.json (license: MIT)
and MIT LICENSE.
- Adds LICENSE explicitly to twenty-ui files so the MIT text is always
in the tarball (verified: npm pack --dry-run lists package/LICENSE, 1.1
kB MIT, license=MIT).
- Points the create-twenty-app scaffold template at 1.0.0-alpha.2.
- Syncs English docs (front-components.mdx, project-structure.mdx),
codex-plugin references, and the cross-doc-contracts.js validator.
## Why twenty-shared is intentionally untouched
packages/twenty-shared/package.json is private:true with no version — it
is only consumed via workspace:* (bundled at build time; twenty-sdk and
twenty-client-sdk list it under devDependencies, never via the registry)
and the scaffold template does not depend on it. There is nothing to
republish; republishing would mean making an internal package public
again. Instead, a maintainer should run npm deprecate on
twenty-shared@0.41.0-canary pointing at this issue. The in-repo state
(license: MIT plus MIT LICENSE) is already correct.
## Maintainer follow-up needed (cannot be done in a PR)
1. Publish 1.0.0-alpha.2 from packages/twenty-ui, then promote it to
latest (currently latest still points at the stale 1.0.0-alpha.0; alpha
points at 1.0.0-alpha.1).
2. npm deprecate the stale artifacts: twenty-ui@1.0.0-alpha.0,
twenty-ui@1.0.0-alpha.1, and twenty-shared@0.41.0-canary.
3. Confirm npm view twenty-ui@1.0.0-alpha.2 license returns MIT and
package/LICENSE in the tarball is the MIT text.
## Verification done
- npm view confirms both published twenty-ui versions are AGPL-3.0 and
predate #23564; repo is MIT.
- npm pack --dry-run on the bumped package includes package/LICENSE
(MIT) with license=MIT.
- No test pins the old version (only the template literal, docs, and
validator — all updated); twenty-apps examples use caret ranges that
resolve forward to alpha.2 automatically, and root yarn.lock uses
workspace:*, so no lockfile churn is needed.
<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/25738?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->
## Context
`gridPosition` predates the layout-mode-aware `position` field. New page
layout widget writes already have enough information to use `position`,
but removing the legacy column and read field in one release is unsafe
because existing widgets still have a null `position`.
This change moves write paths to `position` while keeping a temporary
read fallback until those rows are backfilled.
## What changed
- Update page layout creation, duplication, validation, rendering,
fixtures, seeds, app examples, and documentation to use the
discriminated `position` model.
- Remove `gridPosition` from GraphQL mutation inputs, OpenAPI write
schemas, application manifests, and SDK authoring types.
- Keep `gridPosition` as a deprecated response field during the
migration window.
- Read `position` first and fall back to `gridPosition` only when the
canonical grid position is absent.
- Add a slow upgrade command focused on backfilling missing `position`
values.
## Rollout and safety
The schema change and data migration are intentionally separate:
1. The application can write only `position` while still reading rows
that contain only `gridPosition`.
2. The slow command backfills only rows where `position IS NULL`,
preserving every existing canonical position.
3. The backfill derives the new shape from the tab layout mode: grid
coordinates for `GRID`, deterministic indices after existing widgets for
`VERTICAL_LIST`, and the canvas discriminator for `CANVAS`.
The legacy response field and database column are not removed in this
release. They can be removed in a later release after the slow migration
has completed across deployed workspaces.
## Breaking change
**Write consumers must migrate from `gridPosition` to `position`:**
**- GraphQL mutations can no longer send `gridPosition`.**
**- App manifests using `gridPosition` must be rebuilt and republished
with `position`. Older manifests will have that field ignored and
receive a layout-mode-specific default position.**
Read consumers remain compatible during this rollout. `gridPosition` is
still queryable as a deprecated nullable field, and canonical `position`
always takes precedence when both values exist.
## Expected impact
- Existing widgets continue rendering before the slow migration runs.
- New and updated widgets no longer depend on the legacy column.
- After the slow migration, widgets use the layout-mode-aware canonical
representation and the legacy read fallback should no longer be
exercised.
## Summary
Bumps all nine scoped **js-yaml resolutions 4.2.0 -> 4.3.0** and lifts
the caret copy, clearing Dependabot alert
[1768](https://github.com/twentyhq/twenty/security/dependabot/1768):
**GHSA-52cp-r559-cp3m / CVE-2026-59869** (high) - YAML merge-key chains
force quadratic CPU consumption, vulnerable `>= 4.0.0, < 4.3.0`, fixed
**4.3.0**. Follow-up to the merge-key DoS fixed in 4.2.0
(GHSA-h67p-54hq-rp68).
## Why the pins move (not drop)
Checked upstream first: all seven 4.1.1 exact-pinners are unchanged at
latest (`@mintlify/cli@4.0.1331`, `@mintlify/common@1.0.1037`,
`@mintlify/prebuild@1.0.1185`, `@mintlify/previewing@4.0.1254`,
`@mintlify/scraping@4.0.902`, `@mintlify/validation@0.1.795`,
`@verdaccio/config@8.1.2` - every one still pins `js-yaml 4.1.1` exact).
front-matter and @istanbuljs/load-nyc-config remain EOL on `^3.13.1`. So
no parent upgrade carries 4.3.0; the existing scoped pins just move up,
plus a recursive `yarn up` for the cosmiconfig caret consumers. The
`//resolutions` doc entry is updated with the new advisory and drop
condition (`>=4.3.0`).
## Verification
- Single `js-yaml 4.3.0` entry remains in the lockfile (no 4.2.0, no
3.x).
- `yarn install --immutable` passes.
- front-matter patch intact (`loader = parser.load`); docs front-matter
parses cleanly on 4.3.0.
- `mintlify validate` reports only pre-existing ChartIcon MDX import
warnings from #23091 (content, unrelated - zero `.mdx` files in this
diff).
- 4.3.0 published 2026-06-26, clears the 3-day age gate.
## What & why
Removes the `twenty-sdk/ui` reexport. Apps now use Twenty UI by
installing
[`twenty-ui@1.0.0-alpha.1`](https://www.npmjs.com/package/twenty-ui/v/1.0.0-alpha.1)
from npm and importing its subpaths directly. The reexport re-exported
types that didn't resolve, forcing typecheck workarounds.
## Changes
- **twenty-sdk**: delete `src/ui/index.ts`, drop the `./ui` export,
remove it from the browser vite build, and rewire the CLI manifest-mock
to `twenty-ui` (`.css` falls through to the empty-CSS loader).
`twenty-ui` stays a devDependency for the CLI fixture tests.
- **Renderer + create-twenty-app template**: import from `twenty-ui`
subpaths; the template pins `twenty-ui@1.0.0-alpha.1`.
- **Docs**: new "Using Twenty UI components" section (install + subpath
imports + `useTheme()` for theme tokens), codex references, and the
cross-doc-contract validator.
The `twenty-for-twenty` / `twenty-slack` example apps are intentionally
left on `twenty-sdk/ui`: they consume the published SDK (which still
ships `./ui`), and `twenty-ui@1.0.0-alpha.1` requires react 19 + a
`monaco-editor` peer the react-18 apps can't satisfy. They migrate once
the SDK is republished.