create-twenty-app 2.45.0 → 2.48.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,70 +1,135 @@
1
- ## Base documentation
2
-
3
- - Getting started:
4
- - https://docs.twenty.com/developers/extend/apps/getting-started/quick-start.md
5
- - https://docs.twenty.com/developers/extend/apps/getting-started/concepts.md
6
- - https://docs.twenty.com/developers/extend/apps/getting-started/project-structure.md
7
- - https://docs.twenty.com/developers/extend/apps/getting-started/local-server.md
8
- - https://docs.twenty.com/developers/extend/apps/getting-started/scaffolding.md
9
- - https://docs.twenty.com/developers/extend/apps/getting-started/troubleshooting.md
10
- - Config:
11
- - https://docs.twenty.com/developers/extend/apps/config/overview.md
12
- - https://docs.twenty.com/developers/extend/apps/config/application.md
13
- - https://docs.twenty.com/developers/extend/apps/config/roles.md
14
- - https://docs.twenty.com/developers/extend/apps/config/install-hooks.md
15
- - https://docs.twenty.com/developers/extend/apps/config/public-assets.md
16
- - Data:
17
- - https://docs.twenty.com/developers/extend/apps/data/overview.md
18
- - https://docs.twenty.com/developers/extend/apps/data/objects.md
19
- - https://docs.twenty.com/developers/extend/apps/data/extending-objects.md
20
- - https://docs.twenty.com/developers/extend/apps/data/relations.md
21
- - Logic:
22
- - https://docs.twenty.com/developers/extend/apps/logic/overview.md
23
- - https://docs.twenty.com/developers/extend/apps/logic/logic-functions.md
24
- - https://docs.twenty.com/developers/extend/apps/logic/skills-and-agents.md
25
- - https://docs.twenty.com/developers/extend/apps/logic/connections.md
26
- - Layout:
27
- - https://docs.twenty.com/developers/extend/apps/layout/overview.md
28
- - https://docs.twenty.com/developers/extend/apps/layout/views.md
29
- - https://docs.twenty.com/developers/extend/apps/layout/navigation-menu-items.md
30
- - https://docs.twenty.com/developers/extend/apps/layout/page-layouts.md
31
- - https://docs.twenty.com/developers/extend/apps/layout/front-components.md
32
- - https://docs.twenty.com/developers/extend/apps/layout/command-menu-items.md
33
- - Operations:
34
- - https://docs.twenty.com/developers/extend/apps/operations/overview.md
35
- - https://docs.twenty.com/developers/extend/apps/operations/cli.md
36
- - https://docs.twenty.com/developers/extend/apps/operations/testing.md
37
- - https://docs.twenty.com/developers/extend/apps/operations/publishing.md
38
- - Rich app example: https://github.com/twentyhq/twenty/tree/main/packages/twenty-apps/examples/postcard
39
-
40
- ## UUID requirement
41
-
42
- - All generated UUIDs must be valid UUID v4.
43
-
44
- ## Common Pitfalls
45
-
46
- - Creating a view without a navigationMenuItem associated. This will make the view available on the left sidebar.
47
- - Creating a front-end component that has a scroll instead of being responsive to its fixed widget height and width, unless it is specifically meant to be used in a canvas tab.
48
-
49
- ## Best practice
50
-
51
- It's highly recommended to create new app entities using `yarn twenty dev:add`. These are the options:
52
-
53
- | Entity type | Command | Generated file |
54
- | -------------------- | ---------------------------------------- | ------------------------------------- |
55
- | Object | `yarn twenty dev:add object` | `src/objects/<name>.ts` |
56
- | Field | `yarn twenty dev:add field` | `src/fields/<name>.ts` |
57
- | Logic function | `yarn twenty dev:add logicFunction` | `src/logic-functions/<name>.ts` |
58
- | Front component | `yarn twenty dev:add frontComponent` | `src/front-components/<name>.tsx` |
59
- | Role | `yarn twenty dev:add role` | `src/roles/<name>.ts` |
60
- | Skill | `yarn twenty dev:add skill` | `src/skills/<name>.ts` |
61
- | Agent | `yarn twenty dev:add agent` | `src/agents/<name>.ts` |
62
- | View | `yarn twenty dev:add view` | `src/views/<name>.ts` |
63
- | Navigation menu item | `yarn twenty dev:add navigationMenuItem` | `src/navigation-menu-items/<name>.ts` |
64
- | Page layout | `yarn twenty dev:add pageLayout` | `src/page-layouts/<name>.ts` |
65
- | Page layout tab | `yarn twenty dev:add pageLayoutTab` | `src/page-layout-tabs/<name>.ts` |
66
- | Command menu item | `yarn twenty dev:add commandMenuItem` | `src/command-menu-items/<name>.ts` |
67
- | View field | `yarn twenty dev:add viewField` | `src/view-fields/<name>.ts` |
68
- | Connection provider | `yarn twenty dev:add connectionProvider` | `src/connection-providers/<name>.ts` |
69
-
70
- This helps automatically generate required IDs etc.
1
+ # Working on this Twenty app
2
+
3
+ This file lists the rules the Twenty build and sync enforce, so an agent gets them right the first time. Install the official agent skills for step-by-step workflows that go beyond it:
4
+
5
+ ```bash
6
+ npx skills add https://github.com/twentyhq/twenty/tree/agent-skills --skill '*'
7
+ ```
8
+
9
+ Skills: `create-app`, `develop-app`, `manage-app`, `publish-app`, `use-twenty-mcp`. When they are installed, follow them.
10
+
11
+ ## Documentation
12
+
13
+ Every page below is served as Markdown when you append `.md` to its URL. The full developer index is at https://docs.twenty.com/_llms/en/developers.md.
14
+
15
+ - Getting started: https://docs.twenty.com/developers/extend/apps/getting-started/ `quick-start`, `concepts`, `project-structure`, `local-server`, `scaffolding`, `troubleshooting`
16
+ - Config: https://docs.twenty.com/developers/extend/apps/config/ `overview`, `application`, `roles`, `install-hooks`, `public-assets`
17
+ - Data: https://docs.twenty.com/developers/extend/apps/data/ `overview`, `objects`, `extending-objects`, `relations`, `system-fields`, `timeline-activity-types`
18
+ - Logic: https://docs.twenty.com/developers/extend/apps/logic/ `overview`, `logic-functions`, `skills-and-agents`, `connections`, `background-jobs`, `key-value-store`, `messaging-channels`, `credits`
19
+ - Layout: https://docs.twenty.com/developers/extend/apps/layout/ `overview`, `views`, `navigation-menu-items`, `page-layouts`, `front-components`, `command-menu-items`
20
+ - Operations: https://docs.twenty.com/developers/extend/apps/operations/ `overview`, `cli`, `sync-and-recovery`, `testing`, `translations`, `publishing`
21
+ - End-to-end tutorial: https://docs.twenty.com/developers/extend/apps/tutorials/document-generator/overview.md
22
+ - Example apps: https://github.com/twentyhq/twenty/tree/main/packages/twenty-apps/examples (`postcard`, `document-generator`, `media-notes`, `hello-world`). The test fixture https://github.com/twentyhq/twenty/tree/main/packages/twenty-apps/fixtures/rich-app exercises every entity type, including cron and database-event triggers, indexes, view fields and timeline activity types.
23
+
24
+ ## Commands
25
+
26
+ | Task | Command |
27
+ | ----------------------------------- | -------------------------------------------------------- |
28
+ | Sync once to the active remote | `yarn twenty apply` (`--no-delete`, `--force`) |
29
+ | Preview what a sync would change | `yarn twenty plan` (writes nothing) |
30
+ | Typecheck against the generated SDK | `yarn twenty dev:typecheck` |
31
+ | Lint | `yarn lint` |
32
+ | Unit tests | `yarn test:unit` |
33
+ | Integration tests (needs a server) | `yarn test` |
34
+ | Run a logic function by hand | `yarn twenty dev:function:exec -n <name> -p '{"k":"v"}'` |
35
+ | Stream logic function logs | `yarn twenty dev:function:logs` |
36
+ | Remove the app from the workspace | `yarn twenty app:uninstall --yes` |
37
+ | Scaffold an entity (interactive) | `yarn twenty dev:add <entityType>` (`--path <dir>`) |
38
+
39
+ - Sync with `yarn twenty apply`. Do not run `yarn twenty dev` (watch mode) from an agent: it never exits and its output is ambiguous in a sandbox.
40
+ - A sync deletes every entity your app owns that the source no longer declares. Without a TTY, a plan that destroys objects or fields stops the sync; review `yarn twenty plan`, then re-run with `--force`, or use `--no-delete` while the source is intentionally partial.
41
+ - Run typecheck and lint once after a batch of edits, not after every file.
42
+ - `apply` typechecks before it syncs and regenerates `twenty-client-sdk` in `node_modules`. Code that queries a brand-new object with `CoreApiClient` fails typecheck on the first apply: sync the data model first, then write the code that uses it.
43
+ - One sync at a time per workspace. Never run several `apply`, `dev` or `app:install` in parallel.
44
+ - Local iteration never needs a `package.json` version bump. The strictly-increasing version rule applies to `app:publish` and `app:install` only.
45
+ - Build and sync errors name the metadata type and `universalIdentifier` of the failing entity. Search the source for that identifier instead of guessing.
46
+
47
+ ## Scaffolding entities
48
+
49
+ Generate entities with a CLI rather than writing them by hand: it produces the file, valid identifiers and the right imports. Take the first option that works:
50
+
51
+ 1. **The standalone `twenty` CLI, when `command -v twenty` finds it.** Run it directly, not through `yarn`. It works with or without a terminal: with `--no-input` it never prompts and exits with code 2 when a required value is missing. It covers objects, fields, logic functions and front components. For an object, pass the three `--create-*` flags so it also generates the table view, navigation menu item and record page layout that make the object visible in the UI:
52
+
53
+ ```bash
54
+ twenty app add object --name invoice --name-plural invoices --create-view --create-navigation-menu-item --create-page-layout --no-input
55
+ twenty app add field --name amount --type NUMBER --object <object-uuid> --no-input
56
+ twenty app add logic-function --name send-invoice --no-input
57
+ twenty app add front-component --name invoice-panel --no-input
58
+ ```
59
+
60
+ 2. **`yarn twenty dev:add <entityType>`, in an interactive terminal only.** It covers every entity type, but it prompts for each value: in an agent's shell it fails at once with `User force closed the prompt`.
61
+ 3. **Neither runs, and the user is available**: ask them to run the exact `yarn twenty dev:add <entityType>` command in their own terminal. For an object, prefer this over writing four files by hand.
62
+ 4. **Otherwise, write the file by hand.** Follow the example on the matching docs page (append `.md` to its URL), or an existing file of the same kind in the app, check it against the types exported by `twenty-sdk/define`, and generate every identifier with `crypto.randomUUID()` instead of inventing one.
63
+
64
+ The table below lists what `dev:add` can generate.
65
+
66
+ | Entity type | Command | Generated file |
67
+ | ---------------------- | ------------------------------------------ | --------------------------------------- |
68
+ | Object | `yarn twenty dev:add object` | `src/objects/<name>.ts` |
69
+ | Field | `yarn twenty dev:add field` | `src/fields/<name>.ts` |
70
+ | Logic function | `yarn twenty dev:add logicFunction` | `src/logic-functions/<name>.ts` |
71
+ | Front component | `yarn twenty dev:add frontComponent` | `src/front-components/<name>.tsx` |
72
+ | Role | `yarn twenty dev:add role` | `src/roles/<name>.ts` |
73
+ | Skill | `yarn twenty dev:add skill` | `src/skills/<name>.ts` |
74
+ | Agent | `yarn twenty dev:add agent` | `src/agents/<name>.ts` |
75
+ | View | `yarn twenty dev:add view` | `src/views/<name>.ts` |
76
+ | View field | `yarn twenty dev:add viewField` | `src/view-fields/<name>.ts` |
77
+ | Navigation menu item | `yarn twenty dev:add navigationMenuItem` | `src/navigation-menu-items/<name>.ts` |
78
+ | Page layout | `yarn twenty dev:add pageLayout` | `src/page-layouts/<name>.ts` |
79
+ | Page layout tab | `yarn twenty dev:add pageLayoutTab` | `src/page-layout-tabs/<name>.ts` |
80
+ | Page layout widget | `yarn twenty dev:add pageLayoutWidget` | `src/page-layout-widgets/<name>.ts` |
81
+ | Command menu item | `yarn twenty dev:add commandMenuItem` | `src/command-menu-items/<name>.ts` |
82
+ | Settings menu item | `yarn twenty dev:add settingsMenuItem` | `src/settings-menu-items/<name>.ts` |
83
+ | Connection provider | `yarn twenty dev:add connectionProvider` | `src/connection-providers/<name>.ts` |
84
+ | Timeline activity type | `yarn twenty dev:add timelineActivityType` | `src/timeline-activity-types/<name>.ts` |
85
+
86
+ `dev:add object` also offers to generate the table view, the navigation menu item, the record page layout and its fields view, which is what makes the object usable. A field added to that object later is not shown on the record page until it is listed in `src/views/<name>-record-page-fields.ts`. Generated files use `fill-later` and `replace-with-existing-...` placeholders for identifiers the scaffolder cannot know; the build does not catch them, so replace every placeholder before syncing.
87
+
88
+ ## Rules the build and sync enforce
89
+
90
+ ### Entity files
91
+
92
+ - An entity is any `.ts` or `.tsx` file in the project whose top-level statement is `export default defineX(...)` as a direct call. Assigning the call to a variable first, calling it through a namespace, or adding `satisfies` makes the build skip the file silently, and a skipped entity is deleted on the next sync. Folder placement is a convention, not a rule.
93
+ - Every entity file runs in Node at build time, front components included. No browser globals at module top level.
94
+ - Exactly one `defineApplication()` per app, and exactly one default role: either a `defineApplicationRole()` (what the scaffold ships) or a `defineRole()` referenced by `defaultRoleUniversalIdentifier` in `defineApplication()`. Never add a second one to an app that already has either. At most one pre-install hook, post-install hook, uninstall hook and health check. The scaffolded `health-check.ts` is that one health check; edit it, never add a second.
95
+ - Object and field names match `^[a-z][a-zA-Z0-9]*$`, singular and plural differ, and neither is a reserved keyword (`user`, `workspace`, `role`, `event`, `type`, `field`, `link`, `address`, `search`, `index`, `plan`, `object`, `relation`, `currency`, `job`, ...). These fail only at sync time.
96
+
97
+ ### Identifiers
98
+
99
+ - `universalIdentifier` must be a UUID of version 4 or higher and unique across the whole manifest, nested items included (view fields, tabs, widgets, select options, triggers, application variables).
100
+ - Never change an identifier after the first sync: the server sees a delete plus a create, and the data goes with the delete.
101
+ - Cross-references are always `universalIdentifier` strings, never imports of the entity. Export the identifier as a named constant and import that constant; this also avoids circular imports between the two sides of a relation. Standard objects and page layouts are in `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS` and `STANDARD_PAGE_LAYOUT_UNIVERSAL_IDENTIFIERS` from `twenty-sdk/define`.
102
+ - Two references use names instead: a database event trigger's `eventName` uses the object's `nameSingular` (`company.created`), and a connection provider's `clientIdVariable` / `clientSecretVariable` use server variable keys.
103
+
104
+ ### Data model
105
+
106
+ - Do not declare `id`, `createdAt`, `updatedAt`, `createdBy`, `updatedBy` or `deletedAt`: Twenty adds them. `name` is the one default field you may declare, and `dev:add object` does so to use it as the label identifier; keep that declaration and its identifier, since removing it injects a different `name` field and breaks the views that reference the old one.
107
+ - A relation is two `FieldType.RELATION` fields that point at each other through `relationTargetFieldMetadataUniversalIdentifier`. The `MANY_TO_ONE` side must set `universalSettings.joinColumnName`. Relating to a standard object still requires declaring the reverse field on it with `defineField({ objectUniversalIdentifier })`.
108
+ - Literal string defaults are quoted inside the string: `defaultValue: "'DRAFT'"`. Unquoted strings are reserved for `'uuid'` and `'now'`. `SELECT` option values are `UPPER_SNAKE_CASE`, and option `color` comes from the Twenty tag colors.
109
+ - Turning an existing field into `isNullable: false` requires a non-null `defaultValue`, or the sync fails.
110
+
111
+ ### Layout
112
+
113
+ - A usable object is object + table view + navigation menu item (`type: OBJECT`) + record page layout. A view or an object without a navigation menu item is not reachable from the sidebar. Color is set on the navigation menu item, not on `defineObject`.
114
+ - Set `layoutMode` on every page layout tab: `VERTICAL_LIST` for record and standalone pages, `GRID` for dashboards. `CANVAS` tabs are deprecated. In a `VERTICAL_LIST` tab, order comes from the `widgets` array and `position` is deprecated; `GRID` widgets and standalone `definePageLayoutWidget()` still need an explicit `position`, or every card lands on row 0, column 0.
115
+ - A widget must fit its width-driven container without scrolling, unless it is the single `heightBehavior: 'TAB_VIEWPORT'` widget of its tab, placed last.
116
+ - Widgets reference app components through `frontComponentUniversalIdentifier`, not `frontComponentId`.
117
+
118
+ ### Front components
119
+
120
+ - The file is `.tsx` and ends with `export default defineFrontComponent({ ... })` in exactly that shape; the build rewrites it.
121
+ - Components run in a Web Worker with a sandboxed, partial `window` and `document`: DOM queries, measurements and `matchMedia` work, but `ResizeObserver`, `canvas`, `scrollIntoView` and portals into `document.body` do not, and most unsupported calls fail silently. Base layout on width, never on height. Import UI from `twenty-ui` subpaths and never `IconsProvider` or `useIcons`.
122
+ - Read workspace data with `CoreApiClient` from `twenty-client-sdk/core`. Call third-party APIs from a logic function, not from the component. Secret application variables never reach a front component.
123
+ - `useRecordId()` is deprecated; use `useSelectedRecordIds()` from `twenty-sdk/front-component`.
124
+
125
+ ### Logic functions
126
+
127
+ - The handler is `(payload, context)`. The payload shape follows the trigger: `RoutePayload` for HTTP routes, `DatabaseEventPayload` (or the batch variant, up to 200 events) for database events, `{}` for cron, `{ previousVersion?, newVersion }` for install hooks.
128
+ - HTTP routes are served under `/s/<path>`; request header names are lowercase. `timeoutSeconds` is between 1 and 900, default 300.
129
+ - `new CoreApiClient()` authenticates from the injected environment and acts as the person who triggered the run, narrowed to the app's role; `runAs: 'application'` uses the app's own role. Never declare `TWENTY_API_URL`, `TWENTY_APP_ACCESS_TOKEN`, `TWENTY_APP_APPLICATION_ACCESS_TOKEN`, `TWENTY_API_KEY`, `TWENTY_FUNCTIONS_URL` or `APPLICATION_ID` as variables: sync rejects them.
130
+ - Import runtime helpers from `twenty-sdk/logic-function` and `twenty-sdk/utils` (`isDefined`, `getPublicAssetUrl`). The `isDefined` exported by `twenty-sdk/define` is a conditional-availability variable and fails the build anywhere outside `conditionalAvailabilityExpression`.
131
+ - Give tool and workflow-action functions a specific `description`: agents choose tools by it.
132
+
133
+ ### Dependencies
134
+
135
+ - `twenty-sdk`, `twenty-client-sdk` and `twenty-ui` stay in `devDependencies`, all at the same version. `dependencies` is only for packages logic functions import at runtime; the runtime layer is capped at 250 MB unpacked.
@@ -31,4 +31,5 @@ Notable changes are documented in [CHANGELOG.md](CHANGELOG.md).
31
31
 
32
32
  - [Twenty Apps documentation](https://docs.twenty.com/developers/extend/apps/getting-started/quick-start)
33
33
  - [twenty-sdk CLI reference](https://www.npmjs.com/package/twenty-sdk)
34
+ - [Agent skills for coding assistants](https://github.com/twentyhq/twenty/tree/agent-skills), and the rules in [AGENTS.md](AGENTS.md)
34
35
  - [Discord](https://discord.gg/cx5n4Jzs57)
@@ -42,8 +42,9 @@ async function checkServer(apiUrl: string) {
42
42
  function writeConfig(apiUrl: string, apiKey: string) {
43
43
  const payload = JSON.stringify(
44
44
  {
45
+ version: 1,
45
46
  remotes: {
46
- local: { apiUrl, apiKey, accessToken: apiKey },
47
+ local: { apiUrl, apiKey, twentyCLIAccessToken: apiKey },
47
48
  },
48
49
  defaultRemote: 'local',
49
50
  },
@@ -10,4 +10,5 @@ export default defineApplication({
10
10
  universalIdentifier: APPLICATION_UNIVERSAL_IDENTIFIER,
11
11
  displayName: APP_DISPLAY_NAME,
12
12
  description: APP_DESCRIPTION,
13
+ logo: 'public/logo.svg',
13
14
  });
@@ -28,12 +28,8 @@ export default definePageLayout({
28
28
  universalIdentifier: MAIN_PAGE_WIDGET_UNIVERSAL_IDENTIFIER,
29
29
  title: ' ',
30
30
  type: 'FRONT_COMPONENT',
31
- position: {
32
- layoutMode: PageLayoutTabLayoutMode.VERTICAL_LIST,
33
- index: 0,
34
- heightBehavior:
35
- PageLayoutWidgetVerticalListHeightBehavior.TAB_VIEWPORT,
36
- },
31
+ heightBehavior:
32
+ PageLayoutWidgetVerticalListHeightBehavior.TAB_VIEWPORT,
37
33
  configuration: {
38
34
  configurationType: 'FRONT_COMPONENT',
39
35
  frontComponentUniversalIdentifier: