refactor(website): replace axios with native fetch (#20967)

## 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)
This commit is contained in:
Félix Malfait
2026-05-27 16:31:39 +02:00
committed by GitHub
parent 92b0e07617
commit dde6df7a26
5 changed files with 18 additions and 34 deletions
-1
View File
@@ -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",
@@ -1,17 +1,18 @@
import axios from 'axios';
import { unstable_cache } from 'next/cache';
export const fetchDiscordMemberCount = unstable_cache(
async (): Promise<number | null> => {
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;
}
@@ -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;
}
@@ -1,5 +1,3 @@
import axios from 'axios';
export async function fetchLatestGithubReleaseTag(): Promise<string | null> {
try {
const headers: Record<string, string> = {
@@ -11,12 +9,15 @@ export async function fetchLatestGithubReleaseTag(): Promise<string | null> {
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;
}
-19
View File
@@ -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"