Some checks failed
App Prod-Parity E2E Dispatch / dispatch (push) Failing after 10s
CD Storybook UI / build (push) Failing after 3m25s
CD Storybook UI / dispatch (push) Has been skipped
CD deploy main / website-changed-files (push) Successful in 18m8s
CI Agent Skills / changed-files-check (push) Successful in 18m9s
CI Create App E2E minimal / changed-files-check (push) Successful in 24s
CI Create App / changed-files-check (push) Successful in 26s
CI Docs / changed-files-check (push) Successful in 26s
CI Emails / changed-files-check (push) Successful in 28s
CI Example App Hello World / changed-files-check (push) Successful in 23s
CI Front / changed-files-check (push) Has been skipped
CI Example App Postcard / changed-files-check (push) Successful in 27s
CI UI / changed-files-check (push) Has been skipped
CI Utils Test / changed-files-check (push) Successful in 45s
CI Twenty Apps / discover (push) Successful in 1m3s
CD deploy main / deploy-main (push) Failing after 3s
CI Agent Skills / agent-skills-validate (push) Has been skipped
CI Create App / create-app-test (lint) (push) Has been skipped
CI Emails / emails-test (push) Has been skipped
CI Front / front-task (lingui:compile) (push) Has been skipped
CI Front / front-task (lint) (push) Has been skipped
CI Example App Postcard / example-app-postcard (push) Has been skipped
CI UI / ui-task (lint) (push) Has been skipped
CI UI / ui-task (pack-size) (push) Has been skipped
CI UI / ui-task (size) (push) Has been skipped
CI UI / ui-task (test) (push) Has been skipped
CI UI / ui-task (typecheck) (push) Has been skipped
CI Utils Test / utils-test (push) Has been skipped
CI Twenty Apps / ${{ matrix.app.name }} (push) Has been skipped
CI Emails / ci-emails-status-check (push) Successful in 2s
CI Example App Hello World / ci-example-app-hello-world-status-check (push) Successful in 2s
CI Example App Postcard / ci-example-app-postcard-status-check (push) Successful in 3s
CI UI / ui-sb-test (push) Has been skipped
CI Utils Test / ci-utils-test-status-check (push) Successful in 2s
CI Twenty Apps / ci-twenty-apps-status-check (push) Successful in 2s
CI UI / ci-ui-status-check (push) Successful in 2s
CI Desktop / desktop (push) Failing after 1m8s
Push docs to Crowdin / Push documentation to Crowdin (push) Failing after 55s
Push translations to Crowdin / Extract and upload translations (push) Failing after 5s
Push website translations to Crowdin / Extract and upload website translations (push) Failing after 5s
CI Create App / create-app-test (test) (push) Has been skipped
CI Create App / create-app-test (typecheck) (push) Has been skipped
CI Docs / docs-lint (push) Has been skipped
CI Example App Hello World / example-app-hello-world (push) Has been skipped
CI Front / front-task (lingui:extract) (push) Has been skipped
CI Front / front-task (test) (push) Has been skipped
CI Front / front-task (typecheck) (push) Has been skipped
CI UI / ui-sb-build (push) Failing after 1m32s
CI Twenty Apps / ${{ matrix.app.name }} (${{ matrix.server-source }}) (push) Has been skipped
CI Agent Skills / agent-skills-publish (push) Has been skipped
CI Create App / ci-create-app-status-check (push) Successful in 2s
CI Agent Skills / agent-skills-remote-source (push) Has been skipped
CI Create App E2E minimal / create-app-e2e-minimal (push) Has been cancelled
CI E2E Main / e2e-test (push) Has been cancelled
CI Front / front-sb-build (push) Has been cancelled
CI Front / front-build (push) Has been cancelled
CI Create App E2E minimal / ci-create-app-e2e-minimal-status-check (push) Has been cancelled
CI E2E Main / ci-e2e-main-status-check (push) Has been cancelled
CI E2E Main / notify-main-ci-failure (push) Has been cancelled
CI E2E Main / qa-scout-comment (push) Has been cancelled
CI Front / front-sb-test (push) Has been cancelled
CI Front / front-sb-screenshots (push) Has been cancelled
CI Front / ci-front-status-check (push) Has been cancelled
DPA Sub-Processor Sync / sync-subprocessors (push) Failing after 3s
AI Catalog Sync / sync-catalog (push) Failing after 2s
109 lines
3.4 KiB
Markdown
109 lines
3.4 KiB
Markdown
# Data Model
|
|
|
|
Use this reference for Twenty app objects, fields, relations, roles, and permissions.
|
|
|
|
## Objects And Fields
|
|
|
|
Objects and fields define the records users will create, view, search, and automate. Model the user's workflow first, then add the smallest set of fields that makes the workflow usable.
|
|
|
|
When adding or modifying data model entities:
|
|
|
|
- Prefer generated app entity patterns from `yarn twenty dev:add`.
|
|
- Use clear object and field names that map to user-facing language.
|
|
- Add relations only when users need to navigate or report across records.
|
|
- Avoid duplicating data that already exists on core Twenty objects.
|
|
- Keep field types specific enough to support filtering, views, and automation.
|
|
|
|
### Usable Object Pattern
|
|
|
|
When the user asks for a new object and does not explicitly restrict the request to schema only, make the object usable in the app by pairing data model work with the minimum layout/navigation surfaces:
|
|
|
|
- Object file in `src/objects/<name>.ts`
|
|
- Table view in `src/views/all-<plural>.ts`
|
|
- Object navigation item in `src/navigation-menu-items/<name>.ts`
|
|
- Record page layout in `src/page-layouts/<name>-record-page-layout.ts`
|
|
- Fields-widget view for the record page in `src/views/<name>-record-page-fields.ts`
|
|
|
|
Use `layout.md` for view, navigation, and page layout details.
|
|
|
|
Objects support `icon`, but object color is not defined on `defineObject()`. Put color on the object navigation item:
|
|
|
|
```ts
|
|
import {
|
|
defineNavigationMenuItem,
|
|
NavigationMenuItemType,
|
|
} from 'twenty-sdk/define';
|
|
|
|
export default defineNavigationMenuItem({
|
|
universalIdentifier: '<uuid>',
|
|
name: '<name>',
|
|
icon: '<IconName>',
|
|
color: '<color>',
|
|
position: 0,
|
|
type: NavigationMenuItemType.OBJECT,
|
|
targetObjectUniversalIdentifier: '<object-uuid>',
|
|
});
|
|
```
|
|
|
|
### Minimal Object Example
|
|
|
|
```ts
|
|
import { defineObject, FieldType } from 'twenty-sdk/define';
|
|
|
|
export const OBJECT_UNIVERSAL_IDENTIFIER = '<uuid>';
|
|
export const NAME_FIELD_UNIVERSAL_IDENTIFIER = '<uuid>';
|
|
|
|
export default defineObject({
|
|
universalIdentifier: OBJECT_UNIVERSAL_IDENTIFIER,
|
|
nameSingular: '<name>',
|
|
namePlural: '<names>',
|
|
labelSingular: '<Name>',
|
|
labelPlural: '<Names>',
|
|
icon: '<IconName>',
|
|
labelIdentifierFieldMetadataUniversalIdentifier:
|
|
NAME_FIELD_UNIVERSAL_IDENTIFIER,
|
|
fields: [
|
|
{
|
|
universalIdentifier: NAME_FIELD_UNIVERSAL_IDENTIFIER,
|
|
type: FieldType.TEXT,
|
|
name: 'name',
|
|
label: 'Name',
|
|
icon: 'IconAbc',
|
|
},
|
|
],
|
|
});
|
|
```
|
|
|
|
### Select Fields
|
|
|
|
Select and multi-select option `value` strings must be uppercase snake case:
|
|
|
|
```ts
|
|
{
|
|
type: FieldType.SELECT,
|
|
name: 'status',
|
|
label: 'Status',
|
|
defaultValue: "'PLANNED'",
|
|
options: [
|
|
{ position: 0, label: 'Planned', value: 'PLANNED', color: 'sky' },
|
|
{ position: 1, label: 'In build', value: 'IN_BUILD', color: 'orange' },
|
|
],
|
|
}
|
|
```
|
|
|
|
For select fields, default values must be quoted string expressions like `"'PLANNED'"`, not plain strings like `'planned'`.
|
|
|
|
## Roles And Permissions
|
|
|
|
Roles should match operational responsibility, not implementation convenience.
|
|
|
|
When adding permissions:
|
|
|
|
- Grant the smallest useful scope.
|
|
- Keep sensitive objects and fields out of broad roles.
|
|
- Check whether the app introduces side effects through logic functions before granting write access.
|
|
|
|
## Verification
|
|
|
|
After data model changes, run the app and verify the objects, fields, and roles appear where the user will manage or use them.
|