Skip to content

Commit

Permalink
[DASH-605] Add profile OG image
Browse files Browse the repository at this point in the history
  • Loading branch information
MananTank committed Dec 17, 2024
1 parent 4698ea5 commit 41e0c25
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 340 deletions.
45 changes: 2 additions & 43 deletions apps/dashboard/src/@/components/blocks/Avatars/GradientAvatar.tsx
Original file line number Diff line number Diff line change
@@ -1,48 +1,15 @@
import { Img } from "@/components/blocks/Img";
import { useMemo } from "react";
import type { ThirdwebClient } from "thirdweb";
import { resolveSchemeWithErrorHandler } from "../../../lib/resolveSchemeWithErrorHandler";
import { cn } from "../../../lib/utils";

const gradients = [
["#fca5a5", "#b91c1c"],
["#fdba74", "#c2410c"],
["#fcd34d", "#b45309"],
["#fde047", "#a16207"],
["#a3e635", "#4d7c0f"],
["#86efac", "#15803d"],
["#67e8f9", "#0e7490"],
["#7dd3fc", "#0369a1"],
["#93c5fd", "#1d4ed8"],
["#a5b4fc", "#4338ca"],
["#c4b5fd", "#6d28d9"],
["#d8b4fe", "#7e22ce"],
["#f0abfc", "#a21caf"],
["#f9a8d4", "#be185d"],
["#fda4af", "#be123c"],
];

function getGradientForString(str: string) {
const number = Math.abs(
str.split("").reduce((acc, b, i) => acc + b.charCodeAt(0) * (i + 1), 0),
);
const index = number % gradients.length;
return gradients[index];
}
import { GradientBlobbie } from "./GradientBlobbie";

export function GradientAvatar(props: {
src: string | undefined;
id: string | undefined;
className: string;
client: ThirdwebClient;
}) {
const gradient = useMemo(() => {
if (!props.id) {
return undefined;
}
return getGradientForString(props.id);
}, [props.id]);

const resolvedSrc = props.src
? resolveSchemeWithErrorHandler({
client: props.client,
Expand All @@ -54,15 +21,7 @@ export function GradientAvatar(props: {
<Img
src={resolvedSrc}
className={cn("rounded-full", props.className)}
fallback={
gradient ? (
<div
style={{
background: `linear-gradient(45deg, ${gradient[0]} 0%, ${gradient[1]} 100%)`,
}}
/>
) : undefined
}
fallback={props.id ? <GradientBlobbie id={props.id} /> : undefined}
/>
);
}
45 changes: 45 additions & 0 deletions apps/dashboard/src/@/components/blocks/Avatars/GradientBlobbie.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Note: This is also used in opengraph-image.tsx
// don't use any hooks or client side stuff here

const gradients = [
["#fca5a5", "#b91c1c"],
["#fdba74", "#c2410c"],
["#fcd34d", "#b45309"],
["#fde047", "#a16207"],
["#a3e635", "#4d7c0f"],
["#86efac", "#15803d"],
["#67e8f9", "#0e7490"],
["#7dd3fc", "#0369a1"],
["#93c5fd", "#1d4ed8"],
["#a5b4fc", "#4338ca"],
["#c4b5fd", "#6d28d9"],
["#d8b4fe", "#7e22ce"],
["#f0abfc", "#a21caf"],
["#f9a8d4", "#be185d"],
["#fda4af", "#be123c"],
];

function getGradientForString(str: string) {
const number = Math.abs(
str.split("").reduce((acc, b, i) => acc + b.charCodeAt(0) * (i + 1), 0),
);
const index = number % gradients.length;
return gradients[index];
}

export function GradientBlobbie(props: {
id: string;
style?: React.CSSProperties;
}) {
const gradient = getGradientForString(props.id);
return (
<div
style={{
...props.style,
background: gradient
? `linear-gradient(45deg, ${gradient[0]} 0%, ${gradient[1]} 100%)`
: undefined,
}}
/>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import { GradientBlobbie } from "@/components/blocks/Avatars/GradientBlobbie";
/* eslint-disable @next/next/no-img-element */
import { getThirdwebClient } from "@/constants/thirdweb.server";
import { resolveSchemeWithErrorHandler } from "@/lib/resolveSchemeWithErrorHandler";
import { notFound } from "next/navigation";
import { ImageResponse } from "next/og";
import { resolveAvatar } from "thirdweb/extensions/ens";
import { shortenIfAddress } from "../../../../utils/usedapp-external";
import { resolveAddressAndEns } from "./resolveAddressAndEns";

export const runtime = "edge";

export const size = {
width: 1200,
height: 630,
};

type PageProps = {
params: Promise<{
addressOrEns: string;
}>;
};

export default async function Image(props: PageProps) {
const client = getThirdwebClient();
const params = await props.params;
const resolvedInfo = await resolveAddressAndEns(params.addressOrEns);

if (!resolvedInfo) {
notFound();
}

const [inter700, profileBackground] = await Promise.all([
fetch(new URL("og-lib/fonts/inter/700.ttf", import.meta.url)).then((res) =>
res.arrayBuffer(),
),
fetch(
new URL("og-lib/assets/profile/background.png", import.meta.url),
).then((res) => res.arrayBuffer()),
]);

const ensImage = resolvedInfo.ensName
? await resolveAvatar({
client: client,
name: resolvedInfo.ensName,
})
: null;

const resolvedENSImageSrc = ensImage
? resolveSchemeWithErrorHandler({
client: client,
uri: ensImage,
})
: null;

return new ImageResponse(
<div
tw="w-full h-full flex justify-center py-20 px-16"
style={{
background: "#0D0D12",
fontFamily: "Inter",
}}
>
<img
// @ts-expect-error - this works fine
src={profileBackground}
width="1200px"
height="630px"
tw="absolute"
alt=""
/>

<div tw="w-full h-full flex flex-col justify-between">
<div tw="flex flex-col w-full">
{resolvedENSImageSrc ? (
<img alt="" tw="w-32 h-32 rounded-full" src={resolvedENSImageSrc} />
) : (
<GradientBlobbie
id={resolvedInfo.address}
style={{
width: "128px",
height: "128px",
borderRadius: "50%",
}}
/>
)}

<h1 tw="text-7xl text-white font-bold my-5">
{resolvedInfo.ensName || shortenIfAddress(resolvedInfo.address)}
</h1>
</div>
<div tw="flex justify-end w-full items-end">
<div tw="flex flex-shrink-0">
<OgBrandIcon />
</div>
</div>
</div>
</div>,
{
...size,
fonts: [
{
data: inter700,
name: "Inter",
weight: 700,
},
],
},
);
}

const OgBrandIcon: React.FC = () => (
// biome-ignore lint/a11y/noSvgWithoutTitle: not needed
<svg
xmlns="http://www.w3.org/2000/svg"
width="59"
height="36"
viewBox="0 0 59 36"
fill="none"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M0.157801 3.02898C-0.425237 1.57299 0.661334 0 2.25144 0H12.1233C13.0509 0 13.8725 0.545996 14.217 1.39099L22.0747 20.7869C22.2868 21.3068 22.2868 21.8918 22.0747 22.4248L17.1322 34.6058C16.3769 36.4647 13.7002 36.4647 12.9449 34.6058L0.157801 3.02898ZM19.227 2.96398C18.697 1.52099 19.7835 0 21.3471 0H29.9469C30.901 0 31.7491 0.584996 32.0671 1.45599L39.2093 20.8519C39.3816 21.3328 39.3816 21.8658 39.2093 22.3598L34.916 34.0208C34.2005 35.9707 31.3913 35.9707 30.6757 34.0208L19.227 2.96398ZM38.5336 0C36.9435 0 35.8569 1.57299 36.4399 3.02898L49.227 34.6058C49.9823 36.4647 52.659 36.4647 53.4143 34.6058L58.3569 22.4248C58.5689 21.8918 58.5689 21.3068 58.3569 20.7869L50.4991 1.39099C50.1546 0.545996 49.333 0 48.4055 0H38.5336Z"
fill="white"
fillOpacity="0.5"
/>
</svg>
);
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,15 @@ export async function generateMetadata(props: PageProps): Promise<Metadata> {
replaceDeployerAddress(resolvedInfo.ensName || resolvedInfo.address),
);

const title = displayName;
const description = `Visit ${displayName}'s profile. See their published contracts and deploy them in one click.`;

return {
title: displayName,
description: `Visit ${displayName}'s profile. See their published contracts and deploy them in one click.`,
title,
description,
openGraph: {
title,
description,
},
};
}
56 changes: 0 additions & 56 deletions apps/dashboard/src/og-lib/url-utils.ts

This file was deleted.

Loading

0 comments on commit 41e0c25

Please sign in to comment.