chore: cleanup repository root structure (#17147)

## Summary

This PR reduces clutter at the repository root to improve navigation on
GitHub. The README is now visible much sooner when browsing the repo.

## Changes

### Deleted from root
- `nx` wrapper script → use `npx nx` instead
- `render.yaml` → no longer used
- `jest.preset.js` → inlined `@nx/jest/preset` directly in each
package's jest.config
- `.prettierrc` → moved config to `package.json`
- `.prettierignore` → patterns already covered by `.gitignore`

### Moved/Consolidated
| From | To |
|------|-----|
| `Makefile` | `packages/twenty-docker/Makefile` (merged) |
| `crowdin-app.yml` | `.github/crowdin-app.yml` |
| `crowdin-docs.yml` | `.github/crowdin-docs.yml` |
| `.vale.ini` | `.github/vale.ini` |
| `tools/eslint-rules/` | `packages/twenty-eslint-rules/` |
| `eslint.config.react.mjs` |
`packages/twenty-front/eslint.config.react.mjs` |

## Result

Root items reduced from ~32 to ~22 (folders + files).

## Files updated

- GitHub workflow files updated to reference new crowdin config paths
- Jest configs updated to use `@nx/jest/preset` directly
- ESLint configs updated with new import paths
- `nx.json` updated with new paths
- `package.json` now includes prettier config and updated workspace
paths
- Dockerfile updated with new eslint-rules path
This commit is contained in:
Félix Malfait 2026-01-14 13:56:30 +01:00 committed by GitHub
parent 6f18eaa3f1
commit 245bd510ae
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
25 changed files with 85 additions and 172 deletions

View file

View file

@ -24,7 +24,7 @@ on:
pull_request:
paths:
- 'packages/twenty-docs/**'
- 'crowdin-docs.yml'
- '.github/crowdin-docs.yml'
- '.github/workflows/docs-i18n-pull.yaml'
concurrency:
@ -78,7 +78,7 @@ jobs:
for lang in $LANGUAGES; do
echo "=== Pulling translations for $lang ==="
crowdin download \
--config crowdin-docs.yml \
--config .github/crowdin-docs.yml \
--token "$CROWDIN_PERSONAL_TOKEN" \
--base-url "https://twenty.api.crowdin.com" \
--language "$lang" \

View file

@ -12,7 +12,7 @@ on:
- 'packages/twenty-docs/**/*.mdx'
- '!packages/twenty-docs/l/**'
- 'packages/twenty-docs/navigation/navigation.template.json'
- 'crowdin-docs.yml'
- '.github/crowdin-docs.yml'
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
@ -43,7 +43,7 @@ jobs:
download_translations: false
localization_branch_name: i18n-docs
base_url: 'https://twenty.api.crowdin.com'
config: 'crowdin-docs.yml'
config: '.github/crowdin-docs.yml'
env:
# Docs translations project
CROWDIN_PROJECT_ID: '2'

View file

@ -89,7 +89,7 @@ jobs:
create_pull_request: false
skip_ref_checkout: true
dryrun_action: false
config: 'crowdin-app.yml'
config: '.github/crowdin-app.yml'
env:
GITHUB_TOKEN: ${{ github.token }}
# App translations project

View file

@ -87,7 +87,7 @@ jobs:
download_translations: false
localization_branch_name: i18n
base_url: 'https://twenty.api.crowdin.com'
config: 'crowdin-app.yml'
config: '.github/crowdin-app.yml'
env:
# App translations project
CROWDIN_PROJECT_ID: '1'

View file

@ -1,4 +0,0 @@
# Add files here to ignore them from prettier formatting
/dist
/coverage
/.nx/cache

View file

@ -1,5 +0,0 @@
{
"singleQuote": true,
"trailingComma": "all",
"endOfLine": "lf"
}

View file

@ -1,48 +0,0 @@
DOCKER_NETWORK=twenty_network
ensure-docker-network:
docker network inspect $(DOCKER_NETWORK) >/dev/null 2>&1 || docker network create $(DOCKER_NETWORK)
postgres-on-docker: ensure-docker-network
docker run -d --network $(DOCKER_NETWORK) \
--name twenty_pg \
-e POSTGRES_USER=postgres \
-e POSTGRES_PASSWORD=postgres \
-e ALLOW_NOSSL=true \
-v twenty_db_data:/var/lib/postgresql/data \
-p 5432:5432 \
postgres:16
@echo "Waiting for PostgreSQL to be ready..."
@until docker exec twenty_pg psql -U postgres -d postgres \
-c 'SELECT pg_is_in_recovery();' 2>/dev/null | grep -q 'f'; do \
sleep 1; \
done
docker exec twenty_pg psql -U postgres -d postgres \
-c "CREATE DATABASE \"default\" WITH OWNER postgres;" \
-c "CREATE DATABASE \"test\" WITH OWNER postgres;"
redis-on-docker: ensure-docker-network
docker run -d --network $(DOCKER_NETWORK) --name twenty_redis -p 6379:6379 redis/redis-stack-server:latest
clickhouse-on-docker: ensure-docker-network
docker run -d --network $(DOCKER_NETWORK) --name twenty_clickhouse -p 8123:8123 -p 9000:9000 -e CLICKHOUSE_PASSWORD=devPassword clickhouse/clickhouse-server:latest \
grafana-on-docker: ensure-docker-network
docker run -d --network $(DOCKER_NETWORK) \
--name twenty_grafana \
-p 4000:3000 \
-e GF_SECURITY_ADMIN_USER=admin \
-e GF_SECURITY_ADMIN_PASSWORD=admin \
-e GF_INSTALL_PLUGINS=grafana-clickhouse-datasource \
-v $(PWD)/packages/twenty-docker/grafana/provisioning/datasources:/etc/grafana/provisioning/datasources \
grafana/grafana-oss:latest
opentelemetry-collector-on-docker: ensure-docker-network
docker run -d --network $(DOCKER_NETWORK) \
--name twenty_otlp_collector \
-p 4317:4317 \
-p 4318:4318 \
-p 13133:13133 \
-v $(PWD)/packages/twenty-docker/otel-collector/otel-collector-config.yaml:/etc/otel-collector-config.yaml \
otel/opentelemetry-collector-contrib:latest \
--config /etc/otel-collector-config.yaml

View file

@ -1,5 +0,0 @@
import { getJestProjects } from '@nx/jest';
export default {
projects: getJestProjects(),
};

View file

@ -1,3 +1,4 @@
const nxPreset = require('@nx/jest/preset').default;
module.exports = { ...nxPreset };

5
nx
View file

@ -1,5 +0,0 @@
#!/bin/bash
command -v node >/dev/null 2>&1 || { echo >&2 "Nx requires NodeJS to be available. To install NodeJS and NPM, see: https://nodejs.org/en/download/ ."; exit 1; }
command -v npm >/dev/null 2>&1 || { echo >&2 "Nx requires npm to be available. To install NodeJS and NPM, see: https://nodejs.org/en/download/ ."; exit 1; }
path_to_root=$(dirname $BASH_SOURCE)
node $path_to_root/.nx/nxw.js $@

View file

@ -222,5 +222,10 @@
"packages/create-twenty-app",
"tools/eslint-rules"
]
},
"prettier": {
"singleQuote": true,
"trailingComma": "all",
"endOfLine": "lf"
}
}

View file

@ -1,7 +1,7 @@
import typescriptParser from '@typescript-eslint/parser';
import path from 'path';
import { fileURLToPath } from 'url';
import reactConfig from '../../eslint.config.react.mjs';
import reactConfig from '../../../../../tools/eslint-rules/eslint.config.react.mjs';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

View file

@ -1,15 +1,21 @@
# Makefile for building Twenty CRM docker images.
# Makefile for building and running Twenty CRM docker containers.
# Set the tag and/or target build platform using make command-line variables assignments.
#
# Optional make variables:
# PLATFORM - defaults to 'linux/amd64'
# TAG - defaults to 'latest'
#
# Example: make
# Example: make PLATFORM=linux/aarch64 TAG=my-tag
# Example: make prod-build
# Example: make PLATFORM=linux/aarch64 TAG=my-tag prod-build
# Example: make postgres-on-docker (for local development)
PLATFORM ?= linux/amd64
TAG ?= latest
DOCKER_NETWORK=twenty_network
# =============================================================================
# Production Image Building
# =============================================================================
prod-build:
@cd ../.. && docker build -f ./packages/twenty-docker/twenty/Dockerfile --platform $(PLATFORM) --tag twenty:$(TAG) . && cd -
@ -25,3 +31,55 @@ prod-website-build:
prod-website-run:
@docker run -d -p 3000:3000 --name twenty-website twenty-website:$(TAG)
# =============================================================================
# Local Development Services
# Run these from the repository root: make -C packages/twenty-docker <target>
# =============================================================================
ensure-docker-network:
docker network inspect $(DOCKER_NETWORK) >/dev/null 2>&1 || docker network create $(DOCKER_NETWORK)
postgres-on-docker: ensure-docker-network
docker run -d --network $(DOCKER_NETWORK) \
--name twenty_pg \
-e POSTGRES_USER=postgres \
-e POSTGRES_PASSWORD=postgres \
-e ALLOW_NOSSL=true \
-v twenty_db_data:/var/lib/postgresql/data \
-p 5432:5432 \
postgres:16
@echo "Waiting for PostgreSQL to be ready..."
@until docker exec twenty_pg psql -U postgres -d postgres \
-c 'SELECT pg_is_in_recovery();' 2>/dev/null | grep -q 'f'; do \
sleep 1; \
done
docker exec twenty_pg psql -U postgres -d postgres \
-c "CREATE DATABASE \"default\" WITH OWNER postgres;" \
-c "CREATE DATABASE \"test\" WITH OWNER postgres;"
redis-on-docker: ensure-docker-network
docker run -d --network $(DOCKER_NETWORK) --name twenty_redis -p 6379:6379 redis/redis-stack-server:latest
clickhouse-on-docker: ensure-docker-network
docker run -d --network $(DOCKER_NETWORK) --name twenty_clickhouse -p 8123:8123 -p 9000:9000 -e CLICKHOUSE_PASSWORD=devPassword clickhouse/clickhouse-server:latest \
grafana-on-docker: ensure-docker-network
docker run -d --network $(DOCKER_NETWORK) \
--name twenty_grafana \
-p 4000:3000 \
-e GF_SECURITY_ADMIN_USER=admin \
-e GF_SECURITY_ADMIN_PASSWORD=admin \
-e GF_INSTALL_PLUGINS=grafana-clickhouse-datasource \
-v $(PWD)/grafana/provisioning/datasources:/etc/grafana/provisioning/datasources \
grafana/grafana-oss:latest
opentelemetry-collector-on-docker: ensure-docker-network
docker run -d --network $(DOCKER_NETWORK) \
--name twenty_otlp_collector \
-p 4317:4317 \
-p 4318:4318 \
-p 13133:13133 \
-v $(PWD)/otel-collector/otel-collector-config.yaml:/etc/otel-collector-config.yaml \
otel/opentelemetry-collector-contrib:latest \
--config /etc/otel-collector-config.yaml

View file

@ -40,4 +40,4 @@ RUN chown -R 1000 /app
# Use non root user with uid 1000
USER 1000
CMD ["/bin/sh", "-c", "npx nx start"]
CMD ["/bin/sh", "-c", "npx nx start"]

View file

@ -8,7 +8,6 @@ COPY ./package.json ./yarn.lock ./.yarnrc.yml ./tsconfig.base.json ./nx.json /ap
COPY ./.yarn/releases /app/.yarn/releases
COPY ./.yarn/patches /app/.yarn/patches
COPY ./.prettierrc /app/
COPY ./packages/twenty-emails/package.json /app/packages/twenty-emails/
COPY ./packages/twenty-server/package.json /app/packages/twenty-server/
COPY ./packages/twenty-server/patches /app/packages/twenty-server/patches

View file

@ -112,7 +112,7 @@ You should run all commands in the following steps from the root of the project.
**Option 2:** If you have docker installed:
```bash
make postgres-on-docker
make -C packages/twenty-docker postgres-on-docker
```
</Tab>
<Tab title="Mac OS">
@ -162,7 +162,7 @@ You should run all commands in the following steps from the root of the project.
**Option 2:** If you have docker installed:
```bash
make postgres-on-docker
make -C packages/twenty-docker postgres-on-docker
```
</Tab>
<Tab title="Windows (WSL)">
@ -179,7 +179,7 @@ You should run all commands in the following steps from the root of the project.
Running Docker on WSL adds an extra layer of complexity.
Only use this option if you are comfortable with the extra steps involved, including turning on [Docker Desktop WSL2](https://docs.docker.com/desktop/wsl).
```bash
make postgres-on-docker
make -C packages/twenty-docker postgres-on-docker
```
</Tab>
</Tabs>
@ -196,7 +196,7 @@ Twenty requires a redis cache to provide the best performance
**Option 2:** If you have docker installed:
```bash
make redis-on-docker
make -C packages/twenty-docker redis-on-docker
```
</Tab>
<Tab title="Mac OS">
@ -209,7 +209,7 @@ Twenty requires a redis cache to provide the best performance
**Option 2:** If you have docker installed:
```bash
make redis-on-docker
make -C packages/twenty-docker redis-on-docker
```
</Tab>
<Tab title="Windows (WSL)">
@ -218,7 +218,7 @@ Twenty requires a redis cache to provide the best performance
**Option 2:** If you have docker installed:
```bash
make redis-on-docker
make -C packages/twenty-docker redis-on-docker
```
</Tab>
</Tabs>

View file

@ -1,7 +1,7 @@
import typescriptParser from '@typescript-eslint/parser';
import path from 'path';
import { fileURLToPath } from 'url';
import reactConfig from '../../eslint.config.react.mjs';
import reactConfig from '../../tools/eslint-rules/eslint.config.react.mjs';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

View file

@ -1,7 +1,7 @@
import typescriptParser from '@typescript-eslint/parser';
import path from 'path';
import { fileURLToPath } from 'url';
import reactConfig from '../../eslint.config.react.mjs';
import reactConfig from '../../tools/eslint-rules/eslint.config.react.mjs';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

View file

@ -1,7 +1,7 @@
import typescriptParser from '@typescript-eslint/parser';
import path from 'path';
import { fileURLToPath } from 'url';
import reactConfig from '../../eslint.config.react.mjs';
import reactConfig from '../../tools/eslint-rules/eslint.config.react.mjs';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

View file

@ -1,83 +0,0 @@
services:
- type: web
name: server
runtime: image
image:
url: twentycrm/twenty:latest
dockerCommand: "sh -c ./scripts/render-run.sh"
autoDeploy: false
plan: standard
envVars:
- key: FRONT_BASE_URL
fromService:
name: server
type: web
envVarKey: RENDER_EXTERNAL_URL
- key: SERVER_URL
fromService:
name: server
type: web
envVarKey: RENDER_EXTERNAL_URL
- key: APP_SECRET
generateValue: true
- key: PG_DATABASE_HOST
fromService:
name: twenty_postgres
type: pserv
property: host
- key: PG_DATABASE_PORT
fromService:
name: twenty_postgres
type: pserv
property: port
- type: worker
name: worker
runtime: image
image:
url: twentycrm/twenty:latest
dockerCommand: "sh -c ./scripts/render-worker.sh"
autoDeploy: false
plan: standard
envVars:
- key: FRONT_BASE_URL
fromService:
name: server
type: web
envVarKey: RENDER_EXTERNAL_URL
- key: SERVER_URL
fromService:
name: server
type: web
envVarKey: RENDER_EXTERNAL_URL
- key: APP_SECRET
generateValue: true
- key: PG_DATABASE_HOST
fromService:
name: twenty_postgres
type: pserv
property: host
- key: PG_DATABASE_PORT
fromService:
name: twenty_postgres
type: pserv
property: port
disk:
name: twenty-disk
mountPath: /.local-storage
sizeGB: 5
- type: pserv
name: twenty_postgres
plan: starter
runtime: image
image:
url: twentycrm/twenty-postgres:latest
autoDeploy: false
disk:
name: data
mountPath: /var/lib/postgresql/data
sizeGB: 10
envVars:
- key: POSTGRES_USER
value: postgres
- key: POSTGRES_PASSWORD
value: postgres

View file

@ -1,4 +1,4 @@
export default {
displayName: 'eslint-rules',
silent: false,