Files
twenty/packages/twenty-companion
Charles Bochet 7c0136b97b feat(deps): migrate frontend to React 19 (#21531)
## What

Migrates the frontend stack from **React 18.3 → 19.2**. The website,
sdk, companion and emails packages were already on React 19; this brings
the remaining holdouts (`twenty-front`, `twenty-ui`,
`twenty-ui-deprecated`, `twenty-front-component-renderer`) and
`twenty-server`'s email rendering onto 19, and pins a single React
version repo-wide.

## Why

React 18.x is now the legacy line. Staying current keeps us on the
patched/maintained branch and unblocks downstream library majors
(react-router 7, mantine 9, etc.) that require React 19 peers.

## Dependency bumps (required by React 19 peers / removed APIs)

| Package | From | To | Reason |
|---|---|---|---|
| react / react-dom | 18.3.1 | 19.2.3 | core |
| @hello-pangea/dnd | 16 | 18 | peer `^18 \|\| ^19` |
| react-datepicker | 6 | 9 | v<7 used removed `findDOMNode`; drops
`@types/react-datepicker` |
| react-data-grid | beta.13 | beta.59 | peer `^19.2`; new render API |
| graphiql (+ @graphiql/react, plugin-explorer) | 3 / 0.23 / 1 | 5 /
0.37 / 5.1 | peer `^18 \|\| ^19` |
| react-helmet-async | 1.3 | **@dr.pogodin/react-helmet** 3.2 | upstream
caps peer at `^18`; drop-in React 19 fork |

A `resolutions` pin enforces a single React (19.2.3) + `@types/react`
(19.2.14) across the monorepo to avoid duplicate copies / type-identity
splits. Versions are the aged lockfile patches (clears the
`npmMinimalAgeGate`).

## Code changes

- **Global `JSX` shim** (`react-jsx-global.d.ts` per package): React 19
moved the `JSX` namespace under `React.JSX`; several deps' published
types (notably `@linaria/react`'s `styled.d.ts`, which types every
`styled.x` via `keyof JSX.IntrinsicElements`) still reference the global
namespace. Without the shim, every styled component degrades to `any`
props.
- **Ref nullability**: `useRef<T>(null)` now returns `RefObject<T |
null>`; widened consumer prop/hook ref types accordingly (incl. the
shared `useListenClickOutside`).
- **react-datepicker v9**: `onChange`/`onSelect` accept `Date | null`,
`calendarStartDay` typing, `ReactDatePickerProps`→`DatePickerProps`,
relaxed the dynamic `selectsMultiple` discriminated union.
- **react-data-grid beta.59**: `formatter`→`renderCell`,
`editor`→`renderEditCell`, `headerRenderer`→`renderHeaderCell`,
`components`→`renderers`, `onRowClick`→`onCellClick`, object-shaped
`useRowSelection`, Set-based selection.
- **dnd style cast**: `@radix-ui/react-popper` augments `CSSProperties`
with a `--radix-*` index signature that dnd's closed `DraggingStyle`
doesn't satisfy → cast at the spread.

## Status / testing

-  `typecheck` green: twenty-front, twenty-ui, twenty-ui-deprecated,
twenty-front-component-renderer, twenty-server
-  build / lint / unit tests / storybook+argos / runtime smoke-test in
progress

Draft until local + CI verification completes. Notable behavior to QA
manually: spreadsheet import (data-grid), date pickers, drag-and-drop
boards/lists, GraphQL playground, page titles/favicon.

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/21531?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->
2026-06-14 15:42:22 +02:00
..
2026-03-04 14:11:57 +00:00
2026-03-04 14:11:57 +00:00
2026-03-04 14:11:57 +00:00
2026-03-04 14:11:57 +00:00
2026-03-04 14:11:57 +00:00
2026-03-04 14:11:57 +00:00
2026-03-04 14:11:57 +00:00
2026-03-04 14:11:57 +00:00
2026-03-04 14:11:57 +00:00
2026-03-04 14:11:57 +00:00

Twenty Desktop

WARNING: This application is a Proof of Concept (POC) and must NOT be used in production. It is intended for demonstration and experimentation purposes only. Security, stability, and performance have not been validated for production use.

This is a demo application that shows off what you can build with the Recall.ai Desktop Recording SDK.

This repo is intended to be a mockup of the kind of experience you can build using the Desktop Recording SDK.

Need help? Reach out to our support team support@recall.ai.

Setup

  • Copy the env.example file to a .env file:

    • cp .env.example .env
  • Replace RECALLAI_API_URL with the base URL for the Recall region that you're using that matches your API key, example:

    • RECALLAI_API_URL=https://us-east-1.recall.ai
  • Modify .env to include your Recall.ai API key:

    • RECALLAI_API_KEY=<your key>

Required: This project also uses live transcription with Assembly AI. You'll need to configure your own Assembly credentials on the Recall.ai dashboard. Follow our AssemblyAI real-time transcription guide to set this up.

If you want to enable the AI summary after a recording is finished, you can specify an OpenRouter API key.

OPENROUTER_KEY=<your key>

Twenty CRM Integration (optional)

To automatically create callRecording records in Twenty when a meeting starts (and mark them as ended when the meeting closes), configure:

TWENTY_API_URL=http://localhost:3000
TWENTY_API_KEY=<your key>

The call-recording Twenty app must be installed in your workspace first (packages/twenty-apps/internal/call-recording). Generate an API key at <your-twenty-instance>/settings/api-webhooks.

To launch the Twenty Desktop application, start the server first, then the app:

npm ci
npm start

Screenshots

Screenshot 2025-06-16 at 10 10 57 PM Screenshot 2025-06-16 at 10 22 44 PM Screenshot 2025-06-16 at 10 14 38 PM