diff --git a/AGENTS.md b/AGENTS.md new file mode 120000 index 00000000000..681311eb9cf --- /dev/null +++ b/AGENTS.md @@ -0,0 +1 @@ +CLAUDE.md \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md index 02205105949..a7e6dfb0302 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,224 +1,49 @@ # CLAUDE.md -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. +Twenty is an open-source CRM — an Nx / Yarn 4 monorepo. Main packages: `twenty-front` (React 18, Jotai, Linaria, Vite), `twenty-server` (NestJS, TypeORM, PostgreSQL, Redis, GraphQL), `twenty-shared` (isomorphic types/utils), `twenty-ui`, `twenty-sdk` (application SDK + CLI), `twenty-e2e-testing` (Playwright). -## Project Overview +Match the surrounding code — the adjacent files in the directory you are editing beat any written rule, including for file naming, which varies by area. -Twenty is an open-source CRM built with modern technologies in a monorepo structure. The codebase is organized as an Nx workspace with multiple packages. +## House rules -## Key Commands +Where this repo differs from your defaults: -### Development -```bash -# Start development environment (frontend + backend + worker) -yarn start +- Short-form `//` comments, never JSDoc blocks; comment only WHY (a constraint the code cannot express, still true for a reader who never saw your change), never WHAT. +- Types over interfaces (except when extending third-party interfaces); string literals over enums (except GraphQL enums); no `any`; descriptive generics (`TData`, not `T`). +- Named exports only. Functional components only. +- Prefer event handlers over `useEffect` for state updates. +- No abbreviations in names (`fieldMetadata`, not `fm`); constants in SCREAMING_SNAKE_CASE; component props types suffixed `Props`. +- Use `twenty-shared/utils` guards (`isDefined`, `isNonEmptyString`, …) and other existing helpers before writing your own — reimplementing an existing util is the most common AI-authored defect here. +- Lingui for user-facing strings; Linaria (zero-runtime, styled-components pattern) for twenty-front styling. +- Test behavior, not implementation: query by user-visible text/roles, `@testing-library/user-event` for interactions. -# Individual package development -npx nx start twenty-front # Start frontend dev server -npx nx start twenty-server # Start backend server -npx nx run twenty-server:worker # Start background worker -``` +Longer-form guides remain in `.cursor/rules/` (from the Cursor era). -### Testing -```bash -# Preferred: run a single test file (fast) -npx jest path/to/test.test.ts --config=packages/PROJECT/jest.config.mjs - -# Run all tests for a package -npx nx test twenty-front # Frontend unit tests -npx nx test twenty-server # Backend unit tests -npx nx run twenty-server:test:integration:with-db-reset # Integration tests with DB reset -# To run an individual test or a pattern of tests, use the following command: -cd packages/{workspace} && npx jest "pattern or filename" - -# Storybook -npx nx storybook:build twenty-front -npx nx storybook:test twenty-front - -# When testing the UI end to end, click on "Continue with Email" and use the prefilled credentials. -``` - -### Code Quality -```bash -# Linting (diff with main - fastest, always prefer this) -npx nx lint:diff-with-main twenty-front -npx nx lint:diff-with-main twenty-server -npx nx lint:diff-with-main twenty-front --configuration=fix # Auto-fix - -# Linting (full project - slower, use only when needed) -npx nx lint twenty-front -npx nx lint twenty-server - -# Type checking -npx nx typecheck twenty-front -npx nx typecheck twenty-server - -# Format code -npx nx fmt twenty-front -npx nx fmt twenty-server -``` - -### Build -```bash -# Build packages (twenty-shared must be built first) -npx nx build twenty-shared -npx nx build twenty-front -npx nx build twenty-server -``` - -### Database Operations -```bash -# Database management -npx nx database:reset twenty-server # Reset database -npx nx run twenty-server:database:init:prod # Initialize database -npx nx run twenty-server:database:migrate:prod # Run instance commands (fast only) - -# Generate an instance command (fast or slow) -npx nx run twenty-server:database:migrate:generate --name --type -``` - -### Database Inspection (Postgres MCP) - -A read-only Postgres MCP server is configured in `.mcp.json`. Use it to: -- Inspect workspace data, metadata, and object definitions while developing -- Verify migration results (columns, types, constraints) after running migrations -- Explore the multi-tenant schema structure (core, metadata, workspace-specific schemas) -- Debug issues by querying raw data to confirm whether a bug is frontend, backend, or data-level -- Inspect metadata tables to debug GraphQL schema generation issues - -This server is read-only — for write operations (reset, migrations, sync), use the CLI commands above. - -### GraphQL -```bash -# Generate GraphQL types (run after schema changes) -npx nx run twenty-front:graphql:generate -npx nx run twenty-front:graphql:generate --configuration=metadata -``` - -## Architecture Overview - -### Tech Stack -- **Frontend**: React 18, TypeScript, Jotai (state management), Linaria (styling), Vite -- **Backend**: NestJS, TypeORM, PostgreSQL, Redis, GraphQL (with GraphQL Yoga) -- **Monorepo**: Nx workspace managed with Yarn 4 - -### Package Structure -``` -packages/ -├── twenty-front/ # React frontend application -├── twenty-server/ # NestJS backend API -├── twenty-ui/ # Shared UI components library -├── twenty-shared/ # Common types and utilities -├── twenty-emails/ # Email templates with React Email -├── twenty-website/ # Next.js marketing website -├── twenty-docs/ # Documentation website -├── twenty-zapier/ # Zapier integration -└── twenty-e2e-testing/ # Playwright E2E tests -``` - -### Key Development Principles -- **Functional components only** (no class components) -- **Named exports only** (no default exports) -- **Types over interfaces** (except when extending third-party interfaces) -- **String literals over enums** (except for GraphQL enums) -- **No 'any' type allowed** — strict TypeScript enforced -- **Event handlers preferred over useEffect** for state updates -- **Props down, events up** — unidirectional data flow -- **Composition over inheritance** -- **No abbreviations** in variable names (`user` not `u`, `fieldMetadata` not `fm`) - -### Naming Conventions -- **Variables/functions**: camelCase -- **Constants**: SCREAMING_SNAKE_CASE -- **Types/Classes**: PascalCase (suffix component props with `Props`, e.g. `ButtonProps`) -- **Files/directories**: kebab-case with descriptive suffixes (`.component.tsx`, `.service.ts`, `.entity.ts`, `.dto.ts`, `.module.ts`) -- **TypeScript generics**: descriptive names (`TData` not `T`) - -### File Structure -- Components under 300 lines, services under 500 lines -- Components in their own directories with tests and stories -- Use `index.ts` barrel exports for clean imports -- Import order: external libraries first, then internal (`@/`), then relative - -### Comments -- Use short-form comments (`//`), not JSDoc blocks -- Explain WHY (business logic), not WHAT -- Do not comment obvious code -- Multi-line comments use multiple `//` lines, not `/** */` - -### State Management -- **Jotai** for global state: atoms for primitive state, selectors for derived state, atom families for dynamic collections -- Component-specific state with React hooks (`useState`, `useReducer` for complex logic) -- GraphQL cache managed by Apollo Client -- Use functional state updates: `setState(prev => prev + 1)` - -### Backend Architecture -- **NestJS modules** for feature organization -- **TypeORM** for database ORM with PostgreSQL -- **GraphQL** API with code-first approach -- **Redis** for caching and session management -- **BullMQ** for background job processing - -### Database & Upgrade Commands -- **PostgreSQL** as primary database -- **Redis** for caching and sessions -- **ClickHouse** for analytics (when enabled) -- When changing entity files, generate an **instance command** (`database:migrate:generate --name --type `) -- **Fast** instance commands handle schema changes; **slow** ones add a `runDataMigration` step for data backfills -- **Workspace commands** iterate over all active/suspended workspaces for per-workspace upgrades -- Commands use `@RegisteredInstanceCommand` and `@RegisteredWorkspaceCommand` decorators for automatic discovery -- Include both `up` and `down` logic in instance commands -- Never delete or rewrite committed instance command `up`/`down` logic -- See `packages/twenty-server/docs/UPGRADE_COMMANDS.md` for full documentation - -### Utility Helpers -Use existing helpers from `twenty-shared` instead of manual type guards: -- `isDefined()`, `isNonEmptyString()`, `isNonEmptyArray()` - -## Development Workflow - -IMPORTANT: Use Context7 for code generation, setup or configuration steps, or library/API documentation. Automatically use the Context7 MCP tools to resolve library IDs and get library docs without waiting for explicit requests. - -### Before Making Changes -1. Always run linting (`lint:diff-with-main`) and type checking after code changes -2. Test changes with relevant test suites (prefer single-file test runs) -3. Ensure instance commands are generated for entity changes (`database:migrate:generate`) -4. Check that GraphQL schema changes are backward compatible -5. Run `graphql:generate` after any GraphQL schema changes - -### Code Style Notes -- Use **Linaria** for styling with zero-runtime CSS-in-JS (styled-components pattern) -- Follow **Nx** workspace conventions for imports -- Use **Lingui** for internationalization -- Apply security first, then formatting (sanitize before format) - -### Testing Strategy -- **Test behavior, not implementation** — focus on user perspective -- **Test pyramid**: 70% unit, 20% integration, 10% E2E -- Query by user-visible elements (text, roles, labels) over test IDs -- Use `@testing-library/user-event` for realistic interactions -- Descriptive test names: "should [behavior] when [condition]" -- Clear mocks between tests with `jest.clearAllMocks()` - -## Dev Environment Setup - -All dev environments (Claude Code web, Cursor, local) use one script: +## Commands ```bash -bash packages/twenty-utils/setup-dev-env.sh +bash packages/twenty-utils/setup-dev-env.sh # Postgres/Redis + DB init; only for tasks needing a running app +yarn start # front + server + worker + +npx jest path/to/file.spec.ts --config=packages//jest.config.mjs # single test file (preferred) +npx nx test twenty-server # package unit tests (same for twenty-front, ...) +npx nx run twenty-server:test:integration:with-db-reset +npx nx storybook:build twenty-front && npx nx storybook:test twenty-front + +npx nx lint:diff-with-main twenty-server # diff-based lint (fast; add --configuration=fix); run with typecheck after changes +npx nx fmt # format +npx nx build twenty-shared # required before building/testing packages that depend on it +npx nx database:reset twenty-server +npx nx run twenty-front:graphql:generate # after GraphQL schema changes (--configuration=metadata for metadata schema) ``` -This handles everything: starts Postgres + Redis (auto-detects local services vs Docker), creates databases, copies `.env` files, and initializes the database schema (runs migrations) on a fresh database. Idempotent — safe to run multiple times. +## Gotchas -- `--docker` — force Docker mode (uses `packages/twenty-docker/docker-compose.dev.yml`) -- `--down` — stop services -- `--reset` — wipe data and restart fresh -- **Skip the setup script** for tasks that only read code — architecture questions, code review, documentation, etc. - -**Note:** CI workflows (GitHub Actions) manage services via Actions service containers and run setup steps individually — they don't use this script. - -## Important Files -- `nx.json` - Nx workspace configuration with task definitions -- `tsconfig.base.json` - Base TypeScript configuration -- `package.json` - Root package with workspace definitions -- `.cursor/rules/` - Detailed development guidelines and best practices +- **`twenty-shared/dist` is per-branch state nothing tracks.** After switching branches or editing `twenty-shared`, run `npx nx build twenty-shared --skip-nx-cache` before trusting any typecheck or test failure in a dependent package. +- **Nx caching can serve a stale pass.** To verify a fix, run `npx tsgo -p tsconfig.json --noEmit` in the package directly rather than `nx typecheck`. +- **Do not commit translation catalogs unless translations are the task.** `lingui extract`/`compile` regenerate `packages/twenty-server/src/engine/core-modules/i18n/locales/*.po` and `locales/generated/*` with thousands of lines of churn as a side effect of touching any `msg` string. The i18n pipeline maintains them; leave them out of your commit. +- **Commit messages must not carry AI attribution.** CI rejects commits containing `@anthropic.com` co-author trailers or "Generated with Claude Code" lines. +- **Upgrade commands** (`packages/twenty-server/src/database/commands/upgrade-version-command/`): add or edit files only under the current `TWENTY_CURRENT_VERSION` directory, with a real epoch-ms timestamp strictly greater than every existing one in that directory — CI enforces both, and the upgrade cursor silently skips a command that sorts before an already-applied one. Include `up` and `down`; never rewrite committed command logic. See `packages/twenty-server/docs/UPGRADE_COMMANDS.md`. +- **Entity file changes need a generated instance command**: `npx nx run twenty-server:database:migrate:generate --name --type ` (slow = adds a data-backfill step). +- A read-only Postgres MCP server is configured in `.mcp.json` for inspecting workspace data, metadata, and migration results. Writes go through the CLI commands above. +- E2E login: click "Continue with Email" and use the prefilled credentials.