Fix Avatar for Vercel.

This commit is contained in:
Mike Cao 2025-10-01 00:00:40 -07:00
parent 581ddc0233
commit 25e8e18b73
3 changed files with 77 additions and 8 deletions

View file

@ -11,17 +11,14 @@
}, },
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "next dev", "dev": "next dev -p 3001 --turbopack",
"dev-turbo": "next dev -p 3001 --turbopack",
"build": "npm-run-all check-env build-db check-db build-tracker build-geo build-app", "build": "npm-run-all check-env build-db check-db build-tracker build-geo build-app",
"build-turbo": "npm-run-all check-env build-db check-db build-tracker build-geo build-app-turbo",
"start": "next start", "start": "next start",
"build-docker": "npm-run-all build-db build-tracker build-geo build-app", "build-docker": "npm-run-all build-db build-tracker build-geo build-app",
"start-docker": "npm-run-all check-db update-tracker set-routes-manifest start-server", "start-docker": "npm-run-all check-db update-tracker set-routes-manifest start-server",
"start-env": "node scripts/start-env.js", "start-env": "node scripts/start-env.js",
"start-server": "node server.js", "start-server": "node server.js",
"build-app": "next build", "build-app": "next build --turbo",
"build-app-turbo": "next build --turbo",
"build-icons": "svgr ./src/assets --out-dir src/components/svg --typescript", "build-icons": "svgr ./src/assets --out-dir src/components/svg --typescript",
"build-components": "tsup", "build-components": "tsup",
"build-tracker": "rollup -c rollup.tracker.config.js", "build-tracker": "rollup -c rollup.tracker.config.js",

48
pnpm-lock.yaml generated
View file

@ -367,6 +367,45 @@ importers:
specifier: ^5.9.3 specifier: ^5.9.3
version: 5.9.3 version: 5.9.3
dist:
dependencies:
chart.js:
specifier: ^4.5.0
version: 4.5.0
chartjs-adapter-date-fns:
specifier: ^3.0.0
version: 3.0.0(chart.js@4.5.0)(date-fns@2.30.0)
colord:
specifier: ^2.9.2
version: 2.9.3
jsonwebtoken:
specifier: ^9.0.2
version: 9.0.2
lucide-react:
specifier: ^0.542.0
version: 0.542.0(react@19.1.1)
pure-rand:
specifier: ^7.0.1
version: 7.0.1
react-simple-maps:
specifier: ^2.3.0
version: 2.3.0(prop-types@15.8.1)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
react-use-measure:
specifier: ^2.0.4
version: 2.1.7(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
react-window:
specifier: ^1.8.6
version: 1.8.11(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
serialize-error:
specifier: ^12.0.0
version: 12.0.0
thenby:
specifier: ^1.3.4
version: 1.3.4
uuid:
specifier: ^11.1.0
version: 11.1.0
packages: packages:
'@ampproject/remapping@2.3.0': '@ampproject/remapping@2.3.0':
@ -5259,6 +5298,11 @@ packages:
peerDependencies: peerDependencies:
react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
lucide-react@0.542.0:
resolution: {integrity: sha512-w3hD8/SQB7+lzU2r4VdFyzzOzKnUjTZIF/MQJGSSvni7Llewni4vuViRppfRAa2guOsY5k4jZyxw/i9DQHv+dw==}
peerDependencies:
react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
lucide-react@0.543.0: lucide-react@0.543.0:
resolution: {integrity: sha512-fpVfuOQO0V3HBaOA1stIiP/A2fPCXHIleRZL16Mx3HmjTYwNSbimhnFBygs2CAfU1geexMX5ItUcWBGUaqw5CA==} resolution: {integrity: sha512-fpVfuOQO0V3HBaOA1stIiP/A2fPCXHIleRZL16Mx3HmjTYwNSbimhnFBygs2CAfU1geexMX5ItUcWBGUaqw5CA==}
peerDependencies: peerDependencies:
@ -13395,6 +13439,10 @@ snapshots:
dependencies: dependencies:
react: 19.1.1 react: 19.1.1
lucide-react@0.542.0(react@19.1.1):
dependencies:
react: 19.1.1
lucide-react@0.543.0(react@19.1.1): lucide-react@0.543.0(react@19.1.1):
dependencies: dependencies:
react: 19.1.1 react: 19.1.1

View file

@ -5,17 +5,41 @@ import { getColor, getPastel } from '@/lib/colors';
const lib = lorelei; const lib = lorelei;
// ✅ Modern UTF-8 safe base64 encoder (no deprecated APIs)
function toBase64(str: string): string {
if (typeof window === 'undefined') {
// Server (Node.js)
return Buffer.from(str, 'utf-8').toString('base64');
} else {
// Browser (UTF-8 safe)
const encoder = new TextEncoder();
const bytes = encoder.encode(str);
let binary = '';
const chunkSize = 0x8000;
for (let i = 0; i < bytes.length; i += chunkSize) {
const chunk = bytes.subarray(i, i + chunkSize);
binary += String.fromCharCode(...chunk);
}
return btoa(binary);
}
}
export function Avatar({ seed, size = 128, ...props }: { seed: string; size?: number }) { export function Avatar({ seed, size = 128, ...props }: { seed: string; size?: number }) {
const backgroundColor = getPastel(getColor(seed), 4); const backgroundColor = getPastel(getColor(seed), 4);
const avatar = useMemo(() => { const avatar = useMemo(() => {
return createAvatar(lib, { const svg = createAvatar(lib, {
...props, ...props,
seed, seed,
size, size,
backgroundColor: [backgroundColor], backgroundColor: [backgroundColor],
}).toDataUri(); }).toString();
}, []);
const base64 = toBase64(svg);
return `data:image/svg+xml;base64,${base64}`;
}, [seed, size, backgroundColor, props]);
return <img src={avatar} alt="Avatar" style={{ borderRadius: '100%', width: size }} />; return <img src={avatar} alt="Avatar" style={{ borderRadius: '100%', width: size }} />;
} }