메인 콘텐츠로 건너뛰기
앱은 현재 알파 테스트 중입니다. 해당 기능은 작동하지만 아직 발전 중입니다.

앱이란 무엇인가요?

앱을 사용하면 Twenty 맞춤설정을 코드로 구축하고 관리할 수 있습니다. 모든 것을 UI에서 구성하는 대신, 데이터 모델과 로직 함수를 코드로 정의합니다 — 이를 통해 더 빠르게 구축·유지 관리하고 여러 워크스페이스에 배포할 수 있습니다. 현재 가능한 작업:
  • 사용자 정의 객체와 필드를 코드로 정의하기(관리형 데이터 모델)
  • 사용자 정의 트리거로 로직 함수 구축
  • 동일한 앱을 여러 워크스페이스에 배포
곧 제공 예정:
  • 사용자 정의 UI 레이아웃 및 컴포넌트

사전 준비

시작하기

공식 스캐폴더를 사용해 새 앱을 만든 다음, 인증하고 개발을 시작하세요:
# 새 앱 초기 구조 생성
npx create-twenty-app@latest my-twenty-app
cd my-twenty-app

# yarn@4를 사용하지 않는 경우
corepack enable
yarn install

# API 키로 인증합니다(입력하라는 메시지가 표시됩니다)
yarn auth:login

# 개발 모드 시작: 로컬 변경 사항이 워크스페이스와 자동으로 동기화됩니다
yarn app:dev
여기에서 다음 작업을 수행할 수 있습니다:
# Add a new entity to your application (guided)
yarn entity:add

# Generate a typed Twenty client and workspace entity types
yarn app:generate

# Watch your application's function logs
yarn function:logs

# Execute a function by name
yarn function:execute -n my-function -p '{"name": "test"}'

# Uninstall the application from the current workspace
yarn app:uninstall

# Display commands' help
yarn help
참고: create-twenty-apptwenty-sdk CLI의 CLI 참고 페이지도 확인하세요.

프로젝트 구조(스캐폴딩됨)

npx create-twenty-app@latest my-twenty-app를 실행하면, 스캐폴더가 다음을 수행합니다:
  • my-twenty-app/에 최소한의 기본 애플리케이션을 복사합니다
  • 로컬 twenty-sdk 종속성과 Yarn 4 구성을 추가합니다
  • twenty CLI와 연결된 설정 파일과 스크립트를 생성합니다
  • 기본 애플리케이션 구성과 기본 함수 역할을 생성합니다
새로 스캐폴딩된 앱은 다음과 같습니다:
my-twenty-app/
  package.json
  yarn.lock
  .gitignore
  .nvmrc
  .yarnrc.yml
  .yarn/
    install-state.gz
  eslint.config.mjs
  tsconfig.json
  README.md
  public/                           # 공개 자산 폴더(이미지, 폰트 등)
  src/
    application.config.ts          # 필수 - 기본 애플리케이션 구성
    default-function.role.ts       # 서버리스 함수의 기본 역할
    hello-world.function.ts        # 서버리스 함수 예제
    hello-world.front-component.tsx # 프런트 컴포넌트 예제
    // 사용자 엔터티 (*.object.ts, *.function.ts, *.front-component.tsx, *.role.ts)

설정보다 관례

애플리케이션은 파일 접미사로 엔티티를 감지하는 관례 우선 접근 방식을 사용합니다. 이를 통해 src/app/ 폴더 내에서 유연하게 구성할 수 있습니다:
파일 접미사엔티티 유형
*.object.ts사용자 정의 객체 정의
*.function.ts서버리스 함수 정의
*.front-component.tsx프런트 컴포넌트 정의
*.role.ts역할 정의

지원되는 폴더 구성 방식

엔티티를 다음 패턴 중 어느 것으로든 구성할 수 있습니다: 전통적(유형별):
src/
├── application.config.ts
├── objects/
│   └── postCard.object.ts
├── functions/
│   └── createPostCard.function.ts
├── components/
│   └── card.front-component.tsx
└── roles/
    └── admin.role.ts
기능 기반:
src/
├── application.config.ts
└── post-card/
    ├── postCard.object.ts
    ├── createPostCard.function.ts
    ├── card.front-component.tsx
    └── postCardAdmin.role.ts
플랫:
src/
├── application.config.ts
├── postCard.object.ts
├── createPostCard.function.ts
├── card.front-component.tsx
└── admin.role.ts
개요:
  • package.json: 앱 이름, 버전, 엔진(Node 24+, Yarn 4)을 선언하고, twenty-sdk와 함께 app:dev, app:generate, entity:add, function:logs, function:execute, app:uninstall, auth:login 같은 스크립트를 추가합니다. 이 스크립트들은 로컬 twenty CLI에 위임됩니다.
  • .gitignore: node_modules, .yarn, generated/(타입드 클라이언트), dist/, build/, 커버리지 폴더, 로그 파일, .env* 파일 등의 일반 산출물을 무시합니다.
  • yarn.lock, .yarnrc.yml, .yarn/: 프로젝트에서 사용하는 Yarn 4 툴체인을 고정하고 구성합니다.
  • .nvmrc: 프로젝트에서 예상하는 Node.js 버전을 고정합니다.
  • eslint.config.mjstsconfig.json: 앱의 TypeScript 소스에 대한 린팅 및 TypeScript 구성을 제공합니다.
  • README.md: 앱 루트에 기본 안내를 담은 간단한 README입니다.
  • public/: 애플리케이션과 함께 제공되는 공개 자산(이미지, 폰트, 정적 파일)을 저장하는 폴더입니다. 여기에 배치된 파일은 동기화 시 업로드되며 런타임에 액세스할 수 있습니다.
  • src/: 애플리케이션을 코드로 정의하는 주요 위치:
    • application.config.ts: 앱의 전역 구성(메타데이터 및 런타임 연결)입니다. 아래의 “Application config”를 참조하세요.
    • *.role.ts: 로직 함수에서 사용하는 역할 정의. 아래의 “Default function role”을 참조하세요.
    • *.object.ts: 사용자 정의 객체 정의.
    • *.function.ts: 로직 함수 정의.
    • *.front-component.tsx: 프런트 컴포넌트 정의.
이후 명령을 실행하면 더 많은 파일과 폴더가 추가됩니다:
  • yarn app:generategenerated/ 폴더를 생성합니다(타입드 Twenty 클라이언트 + 워크스페이스 타입).
  • yarn entity:add는 사용자 정의 객체, 함수, 프런트 컴포넌트 또는 역할에 대한 엔티티 정의 파일을 src/ 아래에 추가합니다.

인증

처음 yarn auth:login을 실행하면 다음을 입력하라는 프롬프트가 표시됩니다: 자격 증명은 사용자별로 ~/.twenty/config.json에 저장됩니다. 여러 프로필을 유지하고 프로필 간에 전환할 수 있습니다.

작업 공간 관리

# Login interactively (recommended)
yarn auth:login

# Login to a specific workspace profile
yarn auth:login --workspace my-custom-workspace

# List all configured workspaces
yarn auth:list

# Switch the default workspace (interactive)
yarn auth:switch

# Switch to a specific workspace
yarn auth:switch production

# Check current authentication status
yarn auth:status
한 번 auth:switch로 작업 공간을 전환하면, 이후의 모든 명령은 기본적으로 해당 작업 공간을 사용합니다. 여전히 --workspace <name>로 일시적으로 재정의할 수 있습니다.

SDK 리소스(타입 및 구성) 사용

twenty-sdk는 앱 내부에서 사용하는 타입드 빌딩 블록과 헬퍼 함수를 제공합니다. 가장 자주 사용하게 될 핵심 요소는 다음과 같습니다.

헬퍼 함수

SDK는 앱 엔티티를 정의할 때 사용할 수 있는, 내장 검증이 포함된 네 가지 헬퍼 함수를 제공합니다:
함수목적
defineApplication()애플리케이션 메타데이터 구성
defineObject()필드가 있는 사용자 정의 객체 정의
defineFunction()핸들러가 있는 로직 함수 정의
defineRole()역할 권한과 객체 접근 구성
이 함수들은 런타임에 구성을 검증하고, 더 나은 IDE 자동 완성과 타입 안정성을 제공합니다.

객체 정의하기

사용자 정의 객체는 워크스페이스의 레코드에 대한 스키마와 동작을 모두 정의합니다. defineObject()를 사용해 내장 검증과 함께 객체를 정의하세요:
// src/app/postCard.object.ts
import { defineObject, FieldType } from 'twenty-sdk';

enum PostCardStatus {
  DRAFT = 'DRAFT',
  SENT = 'SENT',
  DELIVERED = 'DELIVERED',
  RETURNED = 'RETURNED',
}

export default defineObject({
  universalIdentifier: '54b589ca-eeed-4950-a176-358418b85c05',
  nameSingular: 'postCard',
  namePlural: 'postCards',
  labelSingular: 'Post Card',
  labelPlural: 'Post Cards',
  description: 'A post card object',
  icon: 'IconMail',
  fields: [
    {
      universalIdentifier: '58a0a314-d7ea-4865-9850-7fb84e72f30b',
      name: 'content',
      type: FieldType.TEXT,
      label: 'Content',
      description: "Postcard's content",
      icon: 'IconAbc',
    },
    {
      universalIdentifier: 'c6aa31f3-da76-4ac6-889f-475e226009ac',
      name: 'recipientName',
      type: FieldType.FULL_NAME,
      label: 'Recipient name',
      icon: 'IconUser',
    },
    {
      universalIdentifier: '95045777-a0ad-49ec-98f9-22f9fc0c8266',
      name: 'recipientAddress',
      type: FieldType.ADDRESS,
      label: 'Recipient address',
      icon: 'IconHome',
    },
    {
      universalIdentifier: '87b675b8-dd8c-4448-b4ca-20e5a2234a1e',
      name: 'status',
      type: FieldType.SELECT,
      label: 'Status',
      icon: 'IconSend',
      defaultValue: `'${PostCardStatus.DRAFT}'`,
      options: [
        { value: PostCardStatus.DRAFT, label: 'Draft', position: 0, color: 'gray' },
        { value: PostCardStatus.SENT, label: 'Sent', position: 1, color: 'orange' },
        { value: PostCardStatus.DELIVERED, label: 'Delivered', position: 2, color: 'green' },
        { value: PostCardStatus.RETURNED, label: 'Returned', position: 3, color: 'orange' },
      ],
    },
    {
      universalIdentifier: 'e06abe72-5b44-4e7f-93be-afc185a3c433',
      name: 'deliveredAt',
      type: FieldType.DATE_TIME,
      label: 'Delivered at',
      icon: 'IconCheck',
      isNullable: true,
      defaultValue: null,
    },
  ],
});
핵심 요점:
  • 내장 검증과 더 나은 IDE 지원을 위해 defineObject()를 사용하세요.
  • universalIdentifier는 배포 전반에서 고유하고 안정적이어야 합니다.
  • 각 필드는 name, type, label 및 고유하고 안정적인 universalIdentifier가 필요합니다.
  • fields 배열은 선택 사항입니다. 사용자 정의 필드 없이도 객체를 정의할 수 있습니다.
  • yarn entity:add를 사용하여 새 객체를 스캐폴딩할 수 있으며, 이름, 필드, 관계 설정 과정을 안내합니다.
기본 필드는 자동으로 생성됩니다. 사용자 정의 객체를 정의하면 Twenty가 name, createdAt, updatedAt, createdBy, position, deletedAt 등의 표준 필드를 자동으로 추가합니다. 이 필드들은 fields 배열에 정의할 필요가 없습니다. 사용자 정의 필드만 추가하세요.

애플리케이션 구성(application.config.ts)

모든 앱에는 다음을 설명하는 단일 application.config.ts 파일이 있습니다:
  • 앱에 대한 정보: 식별자, 표시 이름, 설명.
  • 함수가 실행되는 방식: 권한을 위해 사용하는 역할.
  • (선택 사항) 변수: 함수에 환경 변수로 노출되는 키–값 쌍.
Use defineApplication() to define your application configuration:
// src/app/application.config.ts
import { defineApplication } from 'twenty-sdk';
import { DEFAULT_ROLE_UNIVERSAL_IDENTIFIER } from './default-function.role';

export default defineApplication({
  universalIdentifier: '4ec0391d-18d5-411c-b2f3-266ddc1c3ef7',
  displayName: 'My Twenty App',
  description: 'My first Twenty app',
  icon: 'IconWorld',
  applicationVariables: {
    DEFAULT_RECIPIENT_NAME: {
      universalIdentifier: '19e94e59-d4fe-4251-8981-b96d0a9f74de',
      description: 'Default recipient name for postcards',
      value: 'Jane Doe',
      isSecret: false,
    },
  },
  roleUniversalIdentifier: DEFAULT_ROLE_UNIVERSAL_IDENTIFIER,
});
노트:
  • universalIdentifier 필드는 고유하고 결정적인 ID입니다. 한 번 생성한 후 동기화 전반에 걸쳐 안정적으로 유지하세요.
  • applicationVariables는 함수의 환경 변수가 됩니다(예: DEFAULT_RECIPIENT_NAMEprocess.env.DEFAULT_RECIPIENT_NAME로 사용 가능).
  • roleUniversalIdentifier must match the role you define in your *.role.ts file (see below).

역할 및 권한

애플리케이션은 워크스페이스의 객체와 작업에 대한 권한을 캡슐화하는 역할을 정의할 수 있습니다. The field roleUniversalIdentifier in application.config.ts designates the default role used by your app’s logic functions.
  • TWENTY_API_KEY로 주입되는 런타임 API 키는 이 기본 함수 역할에서 파생됩니다.
  • 타입드 클라이언트는 해당 역할에 부여된 권한으로 제한됩니다.
  • 최소 권한 원칙을 따르세요. 함수에 필요한 권한만 가진 전용 역할을 만들고, 해당 역할의 universal identifier를 참조하세요.
기본 함수 역할(*.role.ts)
새 앱을 스캐폴딩하면, CLI가 기본 역할 파일도 생성합니다. defineRole()을 사용해 내장 검증과 함께 역할을 정의하세요:
// src/app/default-function.role.ts
import { defineRole, PermissionFlag } from 'twenty-sdk';

export const DEFAULT_ROLE_UNIVERSAL_IDENTIFIER =
  'b648f87b-1d26-4961-b974-0908fd991061';

export default defineRole({
  universalIdentifier: DEFAULT_ROLE_UNIVERSAL_IDENTIFIER,
  label: 'Default function role',
  description: 'Default role for function Twenty client',
  canReadAllObjectRecords: false,
  canUpdateAllObjectRecords: false,
  canSoftDeleteAllObjectRecords: false,
  canDestroyAllObjectRecords: false,
  canUpdateAllSettings: false,
  canBeAssignedToAgents: false,
  canBeAssignedToUsers: false,
  canBeAssignedToApiKeys: false,
  objectPermissions: [
    {
      objectUniversalIdentifier: '9f9882af-170c-4879-b013-f9628b77c050',
      canReadObjectRecords: true,
      canUpdateObjectRecords: true,
      canSoftDeleteObjectRecords: false,
      canDestroyObjectRecords: false,
    },
  ],
  fieldPermissions: [
    {
      objectUniversalIdentifier: '9f9882af-170c-4879-b013-f9628b77c050',
      fieldUniversalIdentifier: 'b2c37dc0-8ae7-470e-96cd-1476b47dfaff',
      canReadFieldValue: false,
      canUpdateFieldValue: false,
    },
  ],
  permissionFlags: [PermissionFlag.APPLICATIONS],
});
The universalIdentifier of this role is then referenced in application.config.ts as roleUniversalIdentifier. 다시 말해:
  • *.role.ts는 기본 함수 역할이 수행할 수 있는 작업을 정의합니다.
  • application.config.ts는 해당 역할을 가리키므로, 함수는 그 권한을 상속받습니다.
노트:
  • 스캐폴딩된 역할에서 시작하여, 최소 권한 원칙에 따라 점진적으로 제한하세요.
  • objectPermissionsfieldPermissions를 함수에 필요한 객체/필드로 교체하세요.
  • permissionFlags는 플랫폼 수준 기능에 대한 액세스를 제어합니다. 최소한으로 유지하고, 필요한 것만 추가하세요.
  • Hello World 앱의 동작 예제를 참조하세요: packages/twenty-apps/hello-world/src/roles/function-role.ts.

로직 함수 구성과 엔트리포인트

각 함수 파일은 defineFunction()을 사용해 핸들러와 선택적 트리거가 포함된 구성을 내보냅니다. 자동 감지를 위해 *.function.ts 파일 접미사를 사용하세요.
// src/app/createPostCard.function.ts
import { defineFunction } from 'twenty-sdk';
import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk';
import Twenty, { type Person } from '~/generated';

const handler = async (params: RoutePayload) => {
  const client = new Twenty(); // generated typed client
  const name = 'name' in params.queryStringParameters
    ? params.queryStringParameters.name ?? process.env.DEFAULT_RECIPIENT_NAME ?? 'Hello world'
    : 'Hello world';

  const result = await client.mutation({
    createPostCard: {
      __args: { data: { name } },
      id: true,
      name: true,
    },
  });
  return result;
};

export default defineFunction({
  universalIdentifier: 'e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf',
  name: 'create-new-post-card',
  timeoutSeconds: 2,
  handler,
  triggers: [
    // Public HTTP route trigger '/s/post-card/create'
    {
      universalIdentifier: 'c9f84c8d-b26d-40d1-95dd-4f834ae5a2c6',
      type: 'route',
      path: '/post-card/create',
      httpMethod: 'GET',
      isAuthRequired: false,
    },
    // Cron trigger (CRON pattern)
    // {
    //   universalIdentifier: 'dd802808-0695-49e1-98c9-d5c9e2704ce2',
    //   type: 'cron',
    //   pattern: '0 0 1 1 *',
    // },
    // Database event trigger
    // {
    //   universalIdentifier: '203f1df3-4a82-4d06-a001-b8cf22a31156',
    //   type: 'databaseEvent',
    //   eventName: 'person.updated',
    //   updatedFields: ['name'],
    // },
  ],
});
일반적인 트리거 유형:
  • route: /s/ 엔드포인트 아래에서 HTTP 경로와 메서드로 함수를 노출합니다:
예: path: '/post-card/create', -> <APP_URL>/s/post-card/create에서 호출
  • cron: CRON 식을 사용하여 예약된 일정으로 함수를 실행합니다.
  • databaseEvent: 워크스페이스 객체 라이프사이클 이벤트에서 실행됩니다. 이벤트 작업이 updated인 경우, 수신할 특정 필드를 updatedFields 배열에 지정할 수 있습니다. 정의하지 않거나 비워두면, 어떤 업데이트든 함수가 트리거됩니다.
예: person.updated
노트:
  • triggers 배열은 선택 사항입니다. 트리거가 없는 함수는 다른 함수에서 호출되는 유틸리티 함수로 사용할 수 있습니다.
  • 하나의 함수에서 여러 트리거 유형을 혼합할 수 있습니다.

라우트 트리거 페이로드

호환성 파괴적 변경(v1.16, 2026년 1월): 라우트 트리거 페이로드 형식이 변경되었습니다. v1.16 이전에는 쿼리 매개변수, 경로 매개변수, 그리고 본문이 페이로드로 직접 전송되었습니다. v1.16부터는 이들이 구조화된 RoutePayload 객체 내부에 중첩됩니다.v1.16 이전:
const handler = async (params) => {
  const { param1, param2 } = params; // Direct access
};
v1.16 이후:
const handler = async (event: RoutePayload) => {
  const { param1, param2 } = event.body; // Access via .body
  const { queryParam } = event.queryStringParameters;
  const { id } = event.pathParameters;
};
기존 함수 마이그레이션 방법: 핸들러에서 params 객체에서 직접 구조 분해하는 대신 event.body, event.queryStringParameters, 또는 event.pathParameters에서 구조 분해하도록 업데이트하세요.
라우트 트리거가 로직 함수를 호출하면, AWS HTTP API v2 형식을 따르는 RoutePayload 객체를 받습니다. twenty-sdk에서 해당 타입을 임포트하세요:
import { defineFunction, type RoutePayload } from 'twenty-sdk';

const handler = async (event: RoutePayload) => {
  // Access request data
  const { headers, queryStringParameters, pathParameters, body } = event;

  // HTTP method and path are available in requestContext
  const { method, path } = event.requestContext.http;

  return { message: 'Success' };
};
RoutePayload 타입은 다음과 같은 구조입니다:
속성유형설명
headersRecord<string, string | undefined>HTTP 헤더(forwardedRequestHeaders에 나열된 항목만)
queryStringParametersRecord<string, string | undefined>쿼리 문자열 매개변수(여러 값은 쉼표로 연결됨)
pathParametersRecord<string, string | undefined>라우트 패턴에서 추출된 경로 매개변수(예: /users/:id{ id: '123' })
본문object | null파싱된 요청 본문(JSON)
isBase64Encoded부울본문이 base64로 인코딩되었는지 여부
requestContext.http.methodstringHTTP 메서드(GET, POST, PUT, PATCH, DELETE)
requestContext.http.pathstring원시 요청 경로

HTTP 헤더 전달

기본적으로 보안상의 이유로 들어오는 요청의 HTTP 헤더는 로직 함수로 전달되지 않습니다. 특정 헤더에 접근하려면 forwardedRequestHeaders 배열에 명시적으로 나열하세요:
export default defineFunction({
  universalIdentifier: 'e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf',
  name: 'webhook-handler',
  handler,
  triggers: [
    {
      universalIdentifier: 'c9f84c8d-b26d-40d1-95dd-4f834ae5a2c6',
      type: 'route',
      path: '/webhook',
      httpMethod: 'POST',
      isAuthRequired: false,
      forwardedRequestHeaders: ['x-webhook-signature', 'content-type'],
    },
  ],
});
핸들러에서 다음과 같이 해당 헤더에 접근할 수 있습니다:
const handler = async (event: RoutePayload) => {
  const signature = event.headers['x-webhook-signature'];
  const contentType = event.headers['content-type'];

  // Validate webhook signature...
  return { received: true };
};
헤더 이름은 소문자로 정규화됩니다. 소문자 키를 사용해 접근하세요(예: event.headers['content-type']).
새 함수를 만드는 방법은 두 가지입니다:
  • 스캐폴딩: yarn entity:add를 실행하고 새 함수를 추가하는 옵션을 선택하세요. 이렇게 하면 핸들러와 구성이 포함된 시작 파일이 생성됩니다.
  • 수동: 새 *.function.ts 파일을 만들고 동일한 패턴에 따라 defineFunction()을 사용하세요.

생성된 타입드 클라이언트

워크스페이스 스키마를 기반으로 generated/에 로컬 타입드 클라이언트를 생성하려면 yarn app:generate를 실행하세요. 함수에서 사용하세요:
import Twenty from '~/generated';

const client = new Twenty();
const { me } = await client.query({ me: { id: true, displayName: true } });
클라이언트는 yarn app:generate로 다시 생성됩니다. 객체를 변경한 후 또는 새 워크스페이스에 온보딩할 때 다시 실행하세요.

로직 함수의 런타임 자격 증명

함수가 Twenty에서 실행될 때, 플랫폼은 코드가 실행되기 전에 자격 증명을 환경 변수로 주입합니다:
  • TWENTY_API_URL: 앱이 대상으로 하는 Twenty API의 기본 URL.
  • TWENTY_API_KEY: 애플리케이션의 기본 함수 역할 범위로 제한된 단기 키.
노트:
  • 생성된 클라이언트에 URL이나 API 키를 전달할 필요가 없습니다. 런타임에 process.env에서 TWENTY_API_URLTWENTY_API_KEY를 읽습니다.
  • The API key’s permissions are determined by the role referenced in your application.config.ts via roleUniversalIdentifier. 이는 애플리케이션의 로직 함수에서 사용하는 기본 역할입니다.
  • 애플리케이션은 최소 권한 원칙을 따르도록 역할을 정의할 수 있습니다. Grant only the permissions your functions need, then point roleUniversalIdentifier to that role’s universal identifier.

Hello World 예제

객체, 함수, 여러 트리거를 보여주는 최소한의 엔드투엔드 예제를 여기에서 살펴보세요:

수동 설정(스캐폴더 없이)

최적의 시작 경험을 위해 create-twenty-app 사용을 권장하지만, 프로젝트를 수동으로 설정할 수도 있습니다. CLI를 전역으로 설치하지 마세요. 대신 twenty-sdk를 로컬 종속성으로 추가하고 package.json에 스크립트를 연결하세요:
yarn add -D twenty-sdk
그런 다음 다음과 같은 스크립트를 추가하세요:
{
  "scripts": {
    "auth:login": "twenty auth:login",
    "auth:logout": "twenty auth:logout",
    "auth:status": "twenty auth:status",
    "auth:switch": "twenty auth:switch",
    "auth:list": "twenty auth:list",
    "app:dev": "twenty app:dev",
    "app:generate": "twenty app:generate",
    "app:uninstall": "twenty app:uninstall",
    "entity:add": "twenty entity:add",
    "function:logs": "twenty function:logs",
    "function:execute": "twenty function:execute",
    "help": "twenty help"
  }
}
이제 Yarn을 통해 동일한 명령을 실행할 수 있습니다. 예: yarn app:dev, yarn app:generate 등.

문제 해결

  • 인증 오류: yarn auth:login를 실행하고 API 키에 필요한 권한이 있는지 확인하세요.
  • 서버에 연결할 수 없음: API URL과 Twenty 서버에 접근 가능한지 확인하세요.
  • 타입 또는 클라이언트가 없거나 오래된 경우: yarn app:generate를 실행하세요.
  • 개발 모드가 동기화되지 않음: yarn app:dev가 실행 중인지, 환경에서 변경 사항을 무시하지 않는지 확인하세요.
Discord 도움말 채널: https://discord.com/channels/1130383047699738754/1130386664812982322