From dde6df7a26b69661fba1837b06de03fa1451c8b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Wed, 27 May 2026 16:31:39 +0200 Subject: [PATCH] refactor(website): replace axios with native fetch (#20967) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Follow-up to #20966 (Stripe fetch client). axios's default Node http adapter on workerd has the same TLS hang the Stripe SDK had — it just doesn't surface today because all three call sites are wrapped in \`unstable_cache(revalidate: 3600)\` and the cache is populated at build time, so misses are rare and the failure mode is a silent \`null\` to the layout. This swaps the three remaining axios calls in \`twenty-website\` for native \`fetch\` and removes axios from \`packages/twenty-website/package.json\`. The package is still used by other workspaces, so yarn.lock keeps the other resolution. Touched call sites: - \`src/lib/releases/fetch-latest-release-tag.ts\` (GitHub releases — runs at build time, cosmetic) - \`src/lib/community/fetch-github-star-count.ts\` (GitHub star count in menu) - \`src/lib/community/fetch-discord-member-count.ts\` (Discord member count in menu) ## Test plan - [ ] After merge + deploy: confirm GitHub star + Discord member counts render in the site menu (non-zero, formatted) - [ ] Confirm \`/releases\` shows the latest tag-gated visible release notes - [ ] No \`axios\` in worker bundle (\`grep axios .open-next/worker.js\` should be empty) --- packages/twenty-website/package.json | 1 - .../community/fetch-discord-member-count.ts | 15 ++++++++------- .../lib/community/fetch-github-star-count.ts | 8 +++++--- .../lib/releases/fetch-latest-release-tag.ts | 9 +++++---- yarn.lock | 19 ------------------- 5 files changed, 18 insertions(+), 34 deletions(-) diff --git a/packages/twenty-website/package.json b/packages/twenty-website/package.json index d27a886270..99127bd037 100644 --- a/packages/twenty-website/package.json +++ b/packages/twenty-website/package.json @@ -24,7 +24,6 @@ "@lottiefiles/dotlottie-react": "^0.18.10", "@tabler/icons-react": "^3.41.1", "@wyw-in-js/babel-preset": "^0.8.1", - "axios": "^1.14.0", "framer-motion": "^11.18.0", "gray-matter": "^4.0.3", "next": "16.1.7", diff --git a/packages/twenty-website/src/lib/community/fetch-discord-member-count.ts b/packages/twenty-website/src/lib/community/fetch-discord-member-count.ts index ad2b2fa9ba..f7d38c72c8 100644 --- a/packages/twenty-website/src/lib/community/fetch-discord-member-count.ts +++ b/packages/twenty-website/src/lib/community/fetch-discord-member-count.ts @@ -1,17 +1,18 @@ -import axios from 'axios'; import { unstable_cache } from 'next/cache'; export const fetchDiscordMemberCount = unstable_cache( async (): Promise => { try { - const response = await axios.get( - 'https://discord.com/api/v10/invites/cx5n4Jzs57', - { - params: { with_counts: true }, - }, + const response = await fetch( + 'https://discord.com/api/v10/invites/cx5n4Jzs57?with_counts=true', ); - return response.data.profile.member_count; + if (!response.ok) return null; + + const data = (await response.json()) as { + profile?: { member_count?: number }; + }; + return data.profile?.member_count ?? null; } catch { return null; } diff --git a/packages/twenty-website/src/lib/community/fetch-github-star-count.ts b/packages/twenty-website/src/lib/community/fetch-github-star-count.ts index feacbe8133..673de84d1f 100644 --- a/packages/twenty-website/src/lib/community/fetch-github-star-count.ts +++ b/packages/twenty-website/src/lib/community/fetch-github-star-count.ts @@ -1,4 +1,3 @@ -import axios from 'axios'; import { unstable_cache } from 'next/cache'; export const fetchGithubStarCount = unstable_cache( @@ -13,12 +12,15 @@ export const fetchGithubStarCount = unstable_cache( headers.Authorization = `Bearer ${process.env.GITHUB_TOKEN}`; } - const response = await axios.get( + const response = await fetch( 'https://api.github.com/repos/twentyhq/twenty', { headers }, ); - return response.data.stargazers_count; + if (!response.ok) return null; + + const data = (await response.json()) as { stargazers_count?: number }; + return data.stargazers_count ?? null; } catch { return null; } diff --git a/packages/twenty-website/src/lib/releases/fetch-latest-release-tag.ts b/packages/twenty-website/src/lib/releases/fetch-latest-release-tag.ts index e1380b5cf1..5197b06252 100644 --- a/packages/twenty-website/src/lib/releases/fetch-latest-release-tag.ts +++ b/packages/twenty-website/src/lib/releases/fetch-latest-release-tag.ts @@ -1,5 +1,3 @@ -import axios from 'axios'; - export async function fetchLatestGithubReleaseTag(): Promise { try { const headers: Record = { @@ -11,12 +9,15 @@ export async function fetchLatestGithubReleaseTag(): Promise { headers.Authorization = `Bearer ${process.env.GITHUB_TOKEN}`; } - const response = await axios.get( + const response = await fetch( 'https://api.github.com/repos/twentyhq/twenty/releases/latest', { headers }, ); - return response.data.tag_name; + if (!response.ok) return null; + + const data = (await response.json()) as { tag_name?: string }; + return data.tag_name ?? null; } catch { return null; } diff --git a/yarn.lock b/yarn.lock index b653a2f3b6..0d2b1c3c3e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -28661,17 +28661,6 @@ __metadata: languageName: node linkType: hard -"axios@npm:^1.14.0": - version: 1.14.0 - resolution: "axios@npm:1.14.0" - dependencies: - follow-redirects: "npm:^1.15.11" - form-data: "npm:^4.0.5" - proxy-from-env: "npm:^2.1.0" - checksum: 10c0/2541f4aa215a7d1842429dad006fc682d82bc0e74bd14500823f7d8cce3bbae0e0a8c328c8538946718f366ab8ce5a4c12e9ad40e5a0f3482ff8bff0cd115d45 - languageName: node - linkType: hard - "axios@npm:^1.9.0": version: 1.13.6 resolution: "axios@npm:1.13.6" @@ -49878,13 +49867,6 @@ __metadata: languageName: node linkType: hard -"proxy-from-env@npm:^2.1.0": - version: 2.1.0 - resolution: "proxy-from-env@npm:2.1.0" - checksum: 10c0/ed01729fd4d094eab619cd7e17ce3698b3413b31eb102c4904f9875e677cd207392795d5b4adee9cec359dfd31c44d5ad7595a3a3ad51c40250e141512281c58 - languageName: node - linkType: hard - "proxy-memoize@npm:3.0.1": version: 3.0.1 resolution: "proxy-memoize@npm:3.0.1" @@ -57101,7 +57083,6 @@ __metadata: "@types/react-dom": "npm:^19" "@types/three": "npm:^0.183.1" "@wyw-in-js/babel-preset": "npm:^0.8.1" - axios: "npm:^1.14.0" babel-plugin-react-compiler: "npm:1.0.0" framer-motion: "npm:^11.18.0" gray-matter: "npm:^4.0.3"