Three breaking changes require action. LogicFunctionExecutionContext gains workspace and user identity; caller authority is now per call site. Catalog keys are role-scoped — existing translations must be re-keyed. The write API separates rename from translate.
Front components gain localStorage, sessionStorage, and recording APIs (getUserMedia, MediaRecorder), backed by the host page with per-app scoping. Declare frontComponentSharedDependencies in package.json to cut component output from ~190 KB to ~1.6 KB.
Manifest authoring expands. Throw RetryableLogicFunctionError for queue retries with backoff. Set isDeprecated: true to retire a variable without data loss. Add writability to restrict writes by layer. Add httpMethods for GET webhook challenges.
⚠️ Breaking changes
- The default record-page stack (view fields, groups, layout, tabs, widgets) now uses deterministic universal identifiers; object renames no longer break view field or widget references. (#23651) by @prastoin
SidePanelExpandTarget.expandchanged from a route descriptor to an opaque callback; any code that constructed this type must be updated. (#23965) by @FelixMalfait- Manifest catalog entries are now keyed per metadata role (object name, field label, tab title, etc.); existing app translation catalogs must be re-keyed to the new role-scoped format. (#24360) by @FelixMalfait
- Rename and translate are now separate write operations; the
metadataTranslationsquery returns provenance-aware rows — update any code that reads or writes metadata display names. (#24374) by @FelixMalfait LogicFunctionExecutionContextnow includesworkspaceId,userId,triggerType, andretryCount; caller authority is declared at each call site with a new second argument — update every handler signature. (#24493) by @FelixMalfait
🌟 Highlights
LogicFunctionExecutionContextis expanded with workspace and user identity; caller authority is now set per call site — every logic function handler must update its signature. (#24493)- Metadata catalog entries are now keyed per role; any app with published translations must re-key its catalog to the new role-scoped format. (#24360)
localStorageandsessionStoragenow work in front components, backed by the host page's storage with per-app and per-user key scoping. (#23761)- Declare
frontComponentSharedDependenciesinpackage.jsonto build one shared library bundle across all front components, cutting per-component size from ~190 KB to ~1.6 KB. (#23773) - Throw
RetryableLogicFunctionError(fromtwenty-sdk/logic-function) to signal a transient failure and trigger automatic queue retries with fixed or exponential backoff. (#24317)
✨ New features
window.localStorageandwindow.sessionStoragenow work inside front components, backed by the host page with per-app and per-user key scoping. (#23761) by @bosiraphael- Add
frontComponentSharedDependenciestopackage.jsonto build one shared library bundle for all front components, cutting per-component output from ~190 KB to ~1.6 KB. (#23773) by @bosiraphael - Set
isDeprecated: trueon aserverVariablesentry to retire it without losing the stored value; the variable stays injected so the app can fall back withprocess.env.NEW_KEY ?? process.env.OLD_KEY. (#23868) by @bosiraphael navigator.mediaDevices.getUserMediaandMediaRecordernow work inside front components via polyfills bridged to the host page. (#24203) by @FelixMalfait- Add
writability?: MetadataWritabilityto any object or field entry in your manifest to restrict writes toOPEN,APPLICATION, orSYSTEMlevel. (#24255) by @abdulrahmancodes - Throw
RetryableLogicFunctionError(imported fromtwenty-sdk/logic-function) to signal a transient failure and trigger automatic queue retries with fixed or exponential backoff. (#24317) by @ehconitin - Add
httpMethods: ['GET', 'POST']toserverRouteTriggerSettingsto accept GET challenge requests from webhook providers; undeclared methods return 405. (#24401) by @emmanuelhb56
💅 Improvements & UX
- Translation catalogs now use message IDs at runtime in both the server and the front-component worker, resolving the previous mismatch between build-time and runtime key shapes. (#24325) by @FelixMalfait
- Manifest placeholder syntax is unified;
${...}expressions that were previously untranslatable are migrated to the extractable format so those strings can now be localized. (#24326) by @FelixMalfait timelineActivity.nameis deprecated in favor oftimelineActivityType; new code should read the type first and fall back to name — physical column removal is planned for a future release. (#24568) by @FelixMalfait
🐛 Bug fixes
- Page layout names (e.g. 'Default Company Layout') are now extracted for translation and resolved per locale, matching other metadata display names. (#24315) by @FelixMalfait
twenty applyandtwenty devno longer delete stored locale rows when the local manifest omits atranslationsblock. (#24408) by @FelixMalfaittwenty devnow schedules exactly one follow-up sync when a file change arrives mid-sync, preventing dropped changes and duplicate concurrent runs. (#24514) by @FelixMalfait
🔧 Developer & API
- Packages temporarily published as
2.31.0-alpha.1; apps scaffolded withcreate-twenty-appautomatically pinned to this prerelease. (#24011) by @prastoin - Alpha suffix removed; all three packages published at the release version. (#24059) by @prastoin
🏗️ Internal changes (12)
- Allow going back to the previous onboarding step (#23716) by @bosiraphael
- Add native call recording transcript tab to the calendar event record page (#23909) by @ehconitin
- Enrich the onboarding chat kickoff with person and workspace context (#23970) by @bosiraphael
- feat(billing): replace the credit balance column with a credit grant ledger (#23973) by @FelixMalfait
- perf(server): remove the compact-storage flag, slice cache demotion, use a plain LIMIT on find-many (#23980) by @charlesBochet
- feat(server): ORM v2, a TypeORM-free workspace read path behind a flag (#23991) by @charlesBochet
- Send file attachments when answering an AI chat question (#24017) by @bosiraphael
- Interface scale preference via root CSS zoom (#24209) by @FelixMalfait
- refactor(i18n) - share the message-id hash and the translatable registry [1/6] (#24300) by @FelixMalfait
- Move in-product explainer videos from feature flagged to GA (#24337) by @Bredo
- feat(workflow): add core-backed workflows index page behind a flag (#24350) by @thomtrp
- Reduce non-AI Sentry trace sampling (#24511) by @bosiraphael
🎉 New contributors
- @DebadityaHait made their first contribution in #23945
- @unchainedio made their first contribution in #23976
- @atharv-sys32 made their first contribution in #23320
- @brunobuddy made their first contribution in #23695
- @pwntr made their first contribution in #24091
- @anamikasingh200 made their first contribution in #24250
- @jihadMo made their first contribution in #24380
- @caveman99 made their first contribution in #24523
Full changelog (35 PRs)
- System record page layout (#23651) by @prastoin
- Allow going back to the previous onboarding step (#23716) by @bosiraphael
- Make localStorage and sessionStorage work in app front components (#23761) by @bosiraphael
- Share front component dependencies through a per-app bundle (#23773) by @bosiraphael
- Add a deprecated attribute to app manifest variables (#23868) by @bosiraphael
- Add native call recording transcript tab to the calendar event record page (#23909) by @ehconitin
- feat(front): expand button and record actions in the side panel footer (#23965) by @FelixMalfait
- chore: bump version to 2.31.0 (#23967) by @twenty-pr
- Enrich the onboarding chat kickoff with person and workspace context (#23970) by @bosiraphael
- feat(billing): replace the credit balance column with a credit grant ledger (#23973) by @FelixMalfait
- perf(server): remove the compact-storage flag, slice cache demotion, use a plain LIMIT on find-many (#23980) by @charlesBochet
- feat(server): ORM v2, a TypeORM-free workspace read path behind a flag (#23991) by @charlesBochet
- chore: set npm packages to 2.31.0-alpha.1 (#24011) by @prastoin
- Send file attachments when answering an AI chat question (#24017) by @bosiraphael
- Remove alpha sufix to npm packages (#24059) by @prastoin
- chore: bump version to 2.32.0 (#24061) by @twenty-pr
- App media recording via standard web API polyfills (compare with #24053) (#24203) by @FelixMalfait
- Interface scale preference via root CSS zoom (#24209) by @FelixMalfait
- feat(sdk): let apps set writability on objects and fields (#24255) by @abdulrahmancodes
- refactor(i18n) - share the message-id hash and the translatable registry [1/6] (#24300) by @FelixMalfait
- fix(i18n): translate page layout names (#24315) by @FelixMalfait
- Add retryable logic function failures with queue backoff (#24317) by @ehconitin
- chore: bump version to 2.33.0 (#24319) by @thomtrp
- refactor(i18n): one runtime key space for translation catalogs (#24325) by @FelixMalfait
- refactor(i18n): one placeholder syntax for every derived label (#24326) by @FelixMalfait
- Move in-product explainer videos from feature flagged to GA (#24337) by @Bredo
- feat(workflow): add core-backed workflows index page behind a flag (#24350) by @thomtrp
- refactor(i18n): key metadata catalog entries per role with message context (#24360) by @FelixMalfait
- Edit metadata translations in the UI: per-entity side panel + translate-or-rename prompt (#24374) by @FelixMalfait
- Let a server route declare which HTTP methods it answers (#24401) by @emmanuelhb56
- Stop a manifest without translations from deleting an application's stored locales (#24408) by @FelixMalfait
- feat(logic-function): give handlers an execution context, and a choice of whose access each call uses (#24493) by @FelixMalfait
- Reduce non-AI Sentry trace sampling (#24511) by @bosiraphael
- fix(sdk): rerun dev sync when changes arrive during sync (#24514) by @FelixMalfait
- Replace timelineActivity.name with a timelineActivityType id (#24568) by @FelixMalfait
Full Changelog: sdk/v2.30.0...sdk/v2.33.0