diff --git a/src/app/frames/token/[chainId]/[address]/opengraph-image.tsx b/src/app/frames/token/[chainId]/[address]/opengraph-image.tsx
new file mode 100644
index 0000000..019c4dd
--- /dev/null
+++ b/src/app/frames/token/[chainId]/[address]/opengraph-image.tsx
@@ -0,0 +1,35 @@
+import { ImageResponse } from "next/og";
+
+export const runtime = "edge";
+
+export const alt = "Hello Frame";
+export const size = {
+ width: 600,
+ height: 400,
+};
+
+export const contentType = "image/png";
+
+interface Props {
+ params: Promise<{
+ chainId: string;
+ address: string;
+ }>;
+}
+
+export default async function Image({ params }: Props) {
+ const { chainId, address } = await params;
+ const token = `eip155:${chainId}/erc20:${address}`;
+
+ return new ImageResponse(
+ (
+
+ ),
+ {
+ ...size,
+ }
+ );
+}
diff --git a/src/app/frames/token/[chainId]/[address]/page.tsx b/src/app/frames/token/[chainId]/[address]/page.tsx
new file mode 100644
index 0000000..d92ba84
--- /dev/null
+++ b/src/app/frames/token/[chainId]/[address]/page.tsx
@@ -0,0 +1,46 @@
+import { Metadata } from "next";
+
+const appUrl = process.env.NEXT_PUBLIC_URL;
+
+interface Props {
+ params: Promise<{
+ chainId: string;
+ address: string;
+ }>;
+}
+
+export async function generateMetadata({ params }: Props): Promise {
+ const { chainId, address } = await params;
+ const token = `eip155:${chainId}/erc20:${address}`;
+
+ const frame = {
+ version: "next",
+ imageUrl: `${appUrl}/frames/token/${chainId}/${address}/opengraph-image`,
+ button: {
+ title: "View Token",
+ action: {
+ type: "view_token",
+ token,
+ },
+ },
+ };
+
+ return {
+ title: "View Token",
+ description: token,
+ openGraph: {
+ title: "View Token",
+ description: token,
+ },
+ other: {
+ "fc:frame": JSON.stringify(frame),
+ },
+ };
+}
+
+export default async function HelloNameFrame({ params }: Props) {
+ const { chainId, address } = await params;
+ const token = `eip155:${chainId}/erc20:${address}`;
+
+ return View token: {token}
;
+}