diff --git a/packages/create-twenty-app/package.json b/packages/create-twenty-app/package.json
index da09b7532d..89fa5f0e61 100644
--- a/packages/create-twenty-app/package.json
+++ b/packages/create-twenty-app/package.json
@@ -1,6 +1,6 @@
{
"name": "create-twenty-app",
- "version": "0.3.0",
+ "version": "0.3.1",
"description": "Command-line interface to create Twenty application",
"main": "dist/cli.cjs",
"bin": "dist/cli.cjs",
diff --git a/packages/create-twenty-app/src/utils/__tests__/app-template.spec.ts b/packages/create-twenty-app/src/utils/__tests__/app-template.spec.ts
index ba5d08fa8c..7eee983d67 100644
--- a/packages/create-twenty-app/src/utils/__tests__/app-template.spec.ts
+++ b/packages/create-twenty-app/src/utils/__tests__/app-template.spec.ts
@@ -67,7 +67,7 @@ describe('copyBaseApplicationProject', () => {
const packageJson = await fs.readJson(packageJsonPath);
expect(packageJson.name).toBe('my-test-app');
expect(packageJson.version).toBe('0.1.0');
- expect(packageJson.dependencies['twenty-sdk']).toBe('0.3.0');
+ expect(packageJson.dependencies['twenty-sdk']).toBe('0.3.1');
expect(packageJson.scripts.sync).toBe('twenty app sync');
expect(packageJson.scripts.dev).toBe('twenty app dev');
});
diff --git a/packages/create-twenty-app/src/utils/app-template.ts b/packages/create-twenty-app/src/utils/app-template.ts
index b0700c4730..9e6c1a8add 100644
--- a/packages/create-twenty-app/src/utils/app-template.ts
+++ b/packages/create-twenty-app/src/utils/app-template.ts
@@ -168,7 +168,7 @@ const createPackageJson = async ({
'lint-fix': 'eslint --fix',
},
dependencies: {
- 'twenty-sdk': '0.3.0',
+ 'twenty-sdk': '0.3.1',
},
devDependencies: {
typescript: '^5.9.3',
diff --git a/packages/twenty-docs/developers/extend/capabilities/apps.mdx b/packages/twenty-docs/developers/extend/capabilities/apps.mdx
index 4aabf645fd..66cbc8767c 100644
--- a/packages/twenty-docs/developers/extend/capabilities/apps.mdx
+++ b/packages/twenty-docs/developers/extend/capabilities/apps.mdx
@@ -280,6 +280,10 @@ Key points:
- The `fields` array is optional — you can define objects without custom fields.
- You can scaffold new objects using `yarn create-entity`, which guides you through naming, fields, and relationships.
+
+**Base fields are created automatically.** When you define a custom object, Twenty automatically adds standard fields such as `name`, `createdAt`, `updatedAt`, `createdBy`, `position`, and `deletedAt`. You don't need to define these in your `fields` array — only add your custom fields.
+
+
You can also define objects using TypeScript decorators. This approach uses class-based syntax with `@Object`, `@Field`, and `@Relation` decorators:
diff --git a/packages/twenty-front/src/modules/settings/serverless-functions/components/tabs/SettingsServerlessFunctionTriggersTab.tsx b/packages/twenty-front/src/modules/settings/serverless-functions/components/tabs/SettingsServerlessFunctionTriggersTab.tsx
index 8724a25386..ef59fa31b0 100644
--- a/packages/twenty-front/src/modules/settings/serverless-functions/components/tabs/SettingsServerlessFunctionTriggersTab.tsx
+++ b/packages/twenty-front/src/modules/settings/serverless-functions/components/tabs/SettingsServerlessFunctionTriggersTab.tsx
@@ -2,6 +2,7 @@ import { H2Title, OverflowingTextWithTooltip } from 'twenty-ui/display';
import { Section } from 'twenty-ui/layout';
import { type ServerlessFunction } from '~/generated/graphql';
import { useLingui } from '@lingui/react/macro';
+import { REACT_APP_SERVER_BASE_URL } from '~/config';
import { SettingsDatabaseEventsForm } from '@/settings/components/SettingsDatabaseEventsForm';
import { FormTextFieldInput } from '@/object-record/record-field/ui/form-types/components/FormTextFieldInput';
import { Table } from '@/ui/layout/table/components/Table';
@@ -122,7 +123,9 @@ export const SettingsServerlessFunctionTriggersTab = ({
{routeTriggers.map((routeTrigger, index) => (
-
+
{routeTrigger.httpMethod}
diff --git a/packages/twenty-sdk/package.json b/packages/twenty-sdk/package.json
index 481fd21f17..52cf85a1c8 100644
--- a/packages/twenty-sdk/package.json
+++ b/packages/twenty-sdk/package.json
@@ -1,6 +1,6 @@
{
"name": "twenty-sdk",
- "version": "0.3.0",
+ "version": "0.3.1",
"main": "dist/index.cjs",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
diff --git a/packages/twenty-sdk/src/cli/__tests__/test-app/src/utils/test-function-2.util.ts b/packages/twenty-sdk/src/cli/__tests__/test-app/src/utils/test-function-2.util.ts
index 3d30602cb8..8849aafbd6 100644
--- a/packages/twenty-sdk/src/cli/__tests__/test-app/src/utils/test-function-2.util.ts
+++ b/packages/twenty-sdk/src/cli/__tests__/test-app/src/utils/test-function-2.util.ts
@@ -1 +1,7 @@
-export const testFunction2 = () => 'testFunction2';
+export const testFunction2 = () => {
+ const Twenty = require('../../generated').default;
+
+ const client = new Twenty();
+
+ return client.query('testQuery');
+};
diff --git a/packages/twenty-sdk/src/cli/commands/app.command.ts b/packages/twenty-sdk/src/cli/commands/app.command.ts
index d357a10ff6..dc809eba4e 100644
--- a/packages/twenty-sdk/src/cli/commands/app.command.ts
+++ b/packages/twenty-sdk/src/cli/commands/app.command.ts
@@ -1,3 +1,4 @@
+import { inspect } from 'util';
import chalk from 'chalk';
import { Command } from 'commander';
import {
@@ -12,6 +13,8 @@ import { formatPath } from '@/cli/utils/format-path';
import { AppGenerateCommand } from '@/cli/commands/app-generate.command';
import { AppLogsCommand } from '@/cli/commands/app-logs.command';
+inspect.defaultOptions.depth = 10;
+
export class AppCommand {
private devCommand = new AppDevCommand();
private syncCommand = new AppSyncCommand();
diff --git a/packages/twenty-sdk/src/cli/utils/__tests__/load-manifest.spec.ts b/packages/twenty-sdk/src/cli/utils/__tests__/load-manifest.spec.ts
index 0d0698ec57..1a3f9f626e 100644
--- a/packages/twenty-sdk/src/cli/utils/__tests__/load-manifest.spec.ts
+++ b/packages/twenty-sdk/src/cli/utils/__tests__/load-manifest.spec.ts
@@ -154,7 +154,7 @@ describe('loadManifest with test-app', () => {
expect(appSources['test-function.function.ts']).toContain('defineFunction');
expect(appSources['default-function.role.ts']).toContain('defineRole');
- expect(shouldGenerate).toBe(false);
+ expect(shouldGenerate).toBe(true);
const expectedRoleId = DEFAULT_FUNCTION_ROLE_UNIVERSAL_IDENTIFIER;
diff --git a/packages/twenty-sdk/src/cli/utils/load-manifest.ts b/packages/twenty-sdk/src/cli/utils/load-manifest.ts
index 302780af21..683759de8a 100644
--- a/packages/twenty-sdk/src/cli/utils/load-manifest.ts
+++ b/packages/twenty-sdk/src/cli/utils/load-manifest.ts
@@ -181,19 +181,24 @@ const loadSources = async (appPath: string): Promise => {
/**
* Check if the app imports from the generated folder.
- * Detects any `import ... from '...generated'` or `import ... from '...generated/...'` pattern.
+ * Detects ESM imports: `import ... from '...generated'` or `import ... from '...generated/...'`
+ * Detects CommonJS requires: `require('...generated')` or `require('...generated/...')`
*/
const checkShouldGenerate = async (appPath: string): Promise => {
const tsFiles = await loadFiles(['src/**/*.ts'], appPath);
- // Matches: import ... from 'generated' or from '.../generated' or from '.../generated/...'
- const generatedImportPattern =
+ // Matches ESM: import ... from 'generated' or from '.../generated' or from '.../generated/...'
+ const esmImportPattern =
/from\s+['"][^'"]*\/generated(?:\/[^'"]*)?['"]|from\s+['"]generated['"]/;
+ // Matches CommonJS: require('generated') or require('.../generated') or require('.../generated/...')
+ const commonJsRequirePattern =
+ /require\s*\(\s*['"][^'"]*\/generated(?:\/[^'"]*)?['"]\s*\)|require\s*\(\s*['"]generated['"]\s*\)/;
+
for (const filepath of tsFiles) {
const content = await fs.readFile(filepath, 'utf8');
- if (generatedImportPattern.test(content)) {
+ if (esmImportPattern.test(content) || commonJsRequirePattern.test(content)) {
return true;
}
}