Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/create-twenty-app/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Create Twenty App is the official scaffolding CLI for building apps on top of [T
- Strong TypeScript support and typed client generation

## Prerequisites
- Node.js 18+ (recommended) and Yarn 4
- Node.js 24+ (recommended) and Yarn 4
- A Twenty workspace and an API key (create one at https://app.twenty.com/settings/api-webhooks)

## Quick start
Expand Down
15 changes: 14 additions & 1 deletion packages/create-twenty-app/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"projectType": "library",
"tags": ["scope:create-app"],
"targets": {
"build": {
"before-build": {
"executor": "nx:run-commands",
"cache": true,
"options": {
Expand All @@ -13,6 +13,19 @@
},
"dependsOn": ["^build", "typecheck"]
},
"build": {
"executor": "nx:run-commands",
"cache": true,
"options": {
"cwd": "packages/create-twenty-app",
"commands": [
"mkdir -p dist/constants/base-application",
"cp -R src/constants/base-application dist/constants",
"cp -R ../../.yarn/releases dist/constants/base-application/.yarn"
]
},
"dependsOn": ["before-build"]
},
"dev": {
"executor": "nx:run-commands",
"dependsOn": ["build"],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
24.5.0
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
yarnPath: .yarn/releases/yarn-4.9.2.cjs

nodeLinker: node-modules
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
This is a [Twenty](https://twenty.com) application project bootstrapped with [`create-twenty-app`](https://www.npmjs.com/package/create-twenty-app).

## Getting Started

First, authenticate to your workspace:

```bash
yarn auth
```

Then, run the development server:

```bash
yarn dev
```

Open your Twenty instance and go to `/settings/applications` section to see the result.

You can start adding twenty entities by running

```bash
yarn create-entity
```

The application auto-updates as you edit the file.

## Learn More

To learn more about Twenty applications, take a look at the following resources:

- [twenty-sdk](https://www.npmjs.com/package/twenty-sdk) - learn about `twenty-sdk` tool.
- [Twenty doc](https://docs.twenty.com/) - Twenty's documentation.
- Join our [Discord](https://discord.gg/cx5n4Jzs57)

You can check out [the Twenty GitHub repository](https://github.com/twentyhq/twenty) - your feedback and contributions are welcome!
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import js from '@eslint/js';
import typescriptEslint from '@typescript-eslint/eslint-plugin';
import typescriptParser from '@typescript-eslint/parser';
import importPlugin from 'eslint-plugin-import';
import preferArrowPlugin from 'eslint-plugin-prefer-arrow';
import prettierPlugin from 'eslint-plugin-prettier';
import unusedImportsPlugin from 'eslint-plugin-unused-imports';

export default [
// Base JS rules
js.configs.recommended,

// Global ignores
{
ignores: ['**/node_modules/**', '**/dist/**', '**/coverage/**'],
},

// Base config for TS/JS files
{
files: ['**/*.{js,jsx,ts,tsx}'],
languageOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
},
plugins: {
prettier: prettierPlugin,
import: importPlugin,
'prefer-arrow': preferArrowPlugin,
'unused-imports': unusedImportsPlugin,
},
rules: {
// General rules (aligned with main project)
'func-style': ['error', 'declaration', { allowArrowFunctions: true }],
'no-console': [
'warn',
{ allow: ['group', 'groupCollapsed', 'groupEnd'] },
],
'no-control-regex': 0,
'no-debugger': 'error',
'no-duplicate-imports': 'error',
'no-undef': 'off',
'no-unused-vars': 'off',

// Import rules
'import/no-relative-packages': 'error',
'import/no-useless-path-segments': 'error',
'import/no-duplicates': ['error', { considerQueryString: true }],

// Prefer arrow functions
'prefer-arrow/prefer-arrow-functions': [
'error',
{
disallowPrototype: true,
singleReturnOnly: false,
classPropertiesAllowed: false,
},
],

// Unused imports
'unused-imports/no-unused-imports': 'warn',
'unused-imports/no-unused-vars': [
'warn',
{
vars: 'all',
varsIgnorePattern: '^_',
args: 'after-used',
argsIgnorePattern: '^_',
},
],

// Prettier (formatting as lint errors if you want)
'prettier/prettier': 'error',
},
},

// TypeScript-specific configuration
{
files: ['**/*.{ts,tsx}'],
languageOptions: {
parser: typescriptParser,
parserOptions: {
ecmaFeatures: {
jsx: true,
},
},
},
plugins: {
'@typescript-eslint': typescriptEslint,
},
rules: {
// Turn off base rule and use TS-aware versions
'no-redeclare': 'off',
'@typescript-eslint/no-redeclare': 'error',

'@typescript-eslint/ban-ts-comment': 'error',
'@typescript-eslint/consistent-type-imports': [
'error',
{
prefer: 'type-imports',
fixStyle: 'inline-type-imports',
},
],
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/interface-name-prefix': 'off',
'@typescript-eslint/no-empty-interface': [
'error',
{
allowSingleExtends: true,
},
],
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-empty-function': 'off',
'@typescript-eslint/no-unused-vars': 'off',
},
},

// Test files (Jest)
{
files: ['**/*.spec.@(ts|tsx|js|jsx)', '**/*.test.@(ts|tsx|js|jsx)'],
languageOptions: {
globals: {
jest: true,
describe: true,
it: true,
expect: true,
beforeEach: true,
afterEach: true,
beforeAll: true,
afterAll: true,
},
},
rules: {
'@typescript-eslint/no-non-null-assertion': 'off',
},
},
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"compileOnSave": false,
"compilerOptions": {
"sourceMap": true,
"declaration": true,
"outDir": "./dist",
"rootDir": ".",
"moduleResolution": "node",
"allowSyntheticDefaultImports": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"importHelpers": true,
"allowUnreachableCode": false,
"strictNullChecks": true,
"alwaysStrict": true,
"noImplicitAny": true,
"strictBindCallApply": false,
"target": "es2018",
"module": "esnext",
"lib": ["es2020", "dom"],
"skipLibCheck": true,
"skipDefaultLibCheck": true,
"resolveJsonModule": true,
},

"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"]
}
29 changes: 10 additions & 19 deletions packages/create-twenty-app/src/create-app.command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,14 @@ import chalk from 'chalk';
import * as fs from 'fs-extra';
import inquirer from 'inquirer';
import * as path from 'path';
import { exec } from 'child_process';
import { promisify } from 'util';
import { copyBaseApplicationProject } from './utils/app-template';
import kebabCase from 'lodash.kebabcase';
import { convertToLabel } from './utils/convert-to-label';
import { tryGitInit } from './utils/try-git-init';
import { install } from './utils/install';

const CURRENT_EXECUTION_DIRECTORY = process.env.INIT_CWD || process.cwd();

const execPromise = promisify(exec);

export class CreateAppCommand {
async execute(directory?: string): Promise<void> {
try {
Expand All @@ -31,18 +29,11 @@ export class CreateAppCommand {
appDirectory,
});

try {
const result = await execPromise('yarn --version', {
cwd: appDirectory,
});
console.log('Installing dependencies using yarn', result.stdout);
await execPromise('yarn', { cwd: appDirectory });
} catch (error: any) {
console.error(chalk.red('yarn install failed:'), error.stdout);
process.exit(1);
}

await this.logSuccess(appDirectory);
await install(appDirectory);

await tryGitInit(appDirectory);

this.logSuccess(appDirectory);
} catch (error) {
console.error(
chalk.red('Initialization failed:'),
Expand Down Expand Up @@ -128,10 +119,10 @@ export class CreateAppCommand {
}

private logSuccess(appDirectory: string): void {
console.log(chalk.green('✅ Application created successfully!'));
console.log(chalk.green('✅ Application created!'));
console.log('');
console.log(chalk.blue('Next steps:'));
console.log(` cd ${appDirectory.split('/').reverse()[0] ?? ''}`);
console.log(' twenty app dev');
console.log(`cd ${appDirectory.split('/').reverse()[0] ?? ''}`);
console.log('twenty app dev');
}
}
Loading