diff --git a/.changeset/pretty-tables-melt.md b/.changeset/pretty-tables-melt.md new file mode 100644 index 0000000..5ba907c --- /dev/null +++ b/.changeset/pretty-tables-melt.md @@ -0,0 +1,5 @@ +--- +"stackspulse": patch +--- + +Add SEO to new tokens page. diff --git a/apps/web/src/app/tokens/[token]/opengraph-image.tsx b/apps/web/src/app/tokens/[token]/opengraph-image.tsx new file mode 100644 index 0000000..e6c4ac5 --- /dev/null +++ b/apps/web/src/app/tokens/[token]/opengraph-image.tsx @@ -0,0 +1,70 @@ +import { env } from "@/env"; +import { stacksTokensApi } from "@/lib/stacks"; +import { notFound } from "next/navigation"; +import { ImageResponse } from "next/og"; + +export const runtime = "edge"; + +export const alt = "About Protocol"; +export const size = { + width: 1012, + height: 506, +}; + +export const contentType = "image/png"; + +interface PageProps { + params: { token: string }; +} + +export default async function Image({ params }: PageProps) { + const tokenInfo = await stacksTokensApi + .getFtMetadata(params.token) + .catch((error) => { + if (error.status === 404) { + return null; + } + throw error; + }); + if (!tokenInfo) { + notFound(); + } + + return new ImageResponse( +
+
+ {/* eslint-disable-next-line @next/next/no-img-element */} + {alt} + {tokenInfo.symbol} +
+
, + { + ...size, + }, + ); +} diff --git a/apps/web/src/app/tokens/[token]/page.tsx b/apps/web/src/app/tokens/[token]/page.tsx index e89947d..7939853 100644 --- a/apps/web/src/app/tokens/[token]/page.tsx +++ b/apps/web/src/app/tokens/[token]/page.tsx @@ -4,6 +4,7 @@ import { TokenStats } from "@/components/Token/TokenStats"; import { TokenTransactionsVolume } from "@/components/Token/TokenTransactionsVolume"; import { stacksTokensApi } from "@/lib/stacks"; import { Container } from "@radix-ui/themes"; +import type { Metadata } from "next"; import { notFound } from "next/navigation"; import { Suspense } from "react"; @@ -13,6 +14,30 @@ interface PageProps { params: { token: string }; } +export async function generateMetadata({ + params, +}: PageProps): Promise { + const tokenInfo = await stacksTokensApi + .getFtMetadata(params.token) + .catch((error) => { + if (error.status === 404) { + return null; + } + throw error; + }); + if (!tokenInfo) { + notFound(); + } + + return { + title: `stackspulse - ${tokenInfo.name}`, + description: `Get the latest ${tokenInfo.name} on-chain stats. Explore holders, transaction volume, and more..`, + alternates: { + canonical: `/tokens/${params.token}`, + }, + }; +} + export default async function ProtocolPage({ params }: PageProps) { const tokenInfo = await stacksTokensApi .getFtMetadata(params.token)