## Summary
Removes the `recoil` dependency entirely from `package.json` and
`twenty-front/package.json`, completing the migration to Jotai as the
sole state management library.
Removes all Recoil infrastructure: `RecoilRoot` wrapper from `App.tsx`
and test decorators, `RecoilDebugObserver`, Recoil-specific ESLint rules
(`use-getLoadable-and-getValue-to-get-atoms`,
`useRecoilCallback-has-dependency-array`), and legacy Recoil utility
hooks/types (`useRecoilComponentState`, `useRecoilComponentValue`,
`createComponentState`, `createFamilyState`, `getSnapshotValue`,
`cookieStorageEffect`, `localStorageEffect`, etc.).
Renames all `V2`-suffixed Jotai state files and types to their canonical
names (e.g., `ComponentStateV2` -> `ComponentState`,
`agentChatInputStateV2` -> `agentChatInputState`, `SelectorCallbacksV2`
-> `SelectorCallbacks`), and removes the now-redundant V1 counterparts.
Updates ~433 files across the codebase to use the renamed Jotai imports,
remove Recoil imports, and clean up test wrappers (`RecoilRootDecorator`
-> `JotaiRootDecorator`).
## Summary
The `lint:changed` command was not using the correct ESLint config for
`twenty-server`, causing it to use the root `eslint.config.mjs` instead
of the package-specific one. This PR fixes the issue and renames the
command to `lint:diff-with-main` for clarity.
## Problem
- `twenty-front` correctly specified `--config
packages/twenty-front/eslint.config.mjs`
- `twenty-server` just called `npx eslint` without specifying a config
- This meant `twenty-server` was missing important rules like:
- `@typescript-eslint/no-explicit-any: 'error'`
- `@stylistic/*` rules (linebreak-style, padding, etc.)
- `import/order` with NestJS patterns
- Custom workspace rules (`@nx/workspace-inject-workspace-repository`,
etc.)
## Solution
1. **Renamed** `lint:changed` to `lint:diff-with-main` to be explicit
about what the command does
2. **Centralized** the configuration in `nx.json` targetDefaults:
- Uses `{projectRoot}` interpolation for paths (resolved by Nx at
runtime)
- Each package automatically uses its own ESLint config
- Packages can override specific options (e.g., file extension pattern)
3. **Simplified** `project.json` files by inheriting from defaults
## Usage
```bash
# Lint only files changed vs main branch
npx nx lint:diff-with-main twenty-front
npx nx lint:diff-with-main twenty-server
# Auto-fix files changed vs main
npx nx lint:diff-with-main twenty-front --configuration=fix
```
## Changes
- **nx.json**: Added `lint:diff-with-main` target default with
configurable pattern
- **twenty-front/project.json**: Simplified to inherit from defaults
- **twenty-server/project.json**: Overrides pattern to include `.json`
files
- **CLAUDE.md** and **.cursor/rules**: Updated documentation
## Summary
This PR adds the `lingui/no-unlocalized-strings` ESLint rule to detect
untranslated strings and fixes translation issues across multiple
components.
## Changes
### ESLint Configuration (`eslint.config.react.mjs`)
- Added comprehensive `ignore` patterns for non-translatable strings
(CSS values, HTML attributes, technical identifiers)
- Added `ignoreNames` for props that don't need translation (className,
data-*, aria-*, etc.)
- Added `ignoreFunctions` for console methods, URL APIs, and other
non-user-facing functions
- Disabled rule for debug files, storybook, and test files
### Components Fixed (~19 files)
- Object record components (field inputs, pickers, merge dialogs)
- Settings components (accounts, admin panel)
- Serverless function components
- Record table and title cell components
## Status
🚧 **Work in Progress** - ~124 files remaining to fix
This PR is being submitted as draft to allow progressive fixing of
remaining translation issues.
## Testing
- Run `npx eslint "src/**/*.tsx"` in `packages/twenty-front` to check
remaining issues
In this PR (1/3)
- introduce view.mainGroupByFieldMetadataId as the new reference
determining which fieldMetadataId is used in a grouped view, in order to
deprecate viewGroup.fieldMetadataId which creates inconsistencies.
view.mainGroupByFieldMetadataId is now filled at every view creation,
though not in use yet.
- Introduce a command to backfill view.mainGroupByFieldMetadataId for
existing views + delete all viewGroup.fieldMetadataId with a
fieldMetadataId that is not view.mainGroupByFieldMetadataId. (It should
concern 37 active workspaces)
- Temporarily disable the option to change a grouped view's
fieldMetadataId as for now it creates inconsistencies. This feature can
be reintroduced when we have done the full migration.
In a next PR
- (2/3) use view.mainGroupByFieldMetadataId instead of
viewGroup.fieldMetadataId. In FE we may keep viewGroup.fieldMetadataId
as a state (TBD). View groups will now be created / deleted as a side
effect of view's mainGroupByFieldMetadataId update.
- (3/3) remove viewGroup.fieldMetadataId
---------
Co-authored-by: Charles Bochet <charles@twenty.com>