diff --git a/package.json b/package.json
index 88e56ce..7df6749 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@neynar/create-farcaster-mini-app",
- "version": "1.2.22",
+ "version": "1.2.23",
"type": "module",
"private": false,
"access": "public",
diff --git a/src/app/api/opengraph-image/route.tsx b/src/app/api/opengraph-image/route.tsx
index 37aa1e8..87d59a6 100644
--- a/src/app/api/opengraph-image/route.tsx
+++ b/src/app/api/opengraph-image/route.tsx
@@ -8,7 +8,7 @@ export async function GET(request: NextRequest) {
const { searchParams } = new URL(request.url);
const fid = searchParams.get('fid');
- const user = await getNeynarUser(Number(fid));
+ const user = fid ? await getNeynarUser(Number(fid)) : null;
return new ImageResponse(
(
diff --git a/src/app/opengraph-image.tsx b/src/app/opengraph-image.tsx
deleted file mode 100644
index 86b07cc..0000000
--- a/src/app/opengraph-image.tsx
+++ /dev/null
@@ -1,24 +0,0 @@
-import { ImageResponse } from "next/og";
-import { APP_NAME } from "~/lib/constants";
-
-export const alt = APP_NAME;
-export const size = {
- width: 600,
- height: 400,
-};
-
-export const contentType = "image/png";
-
-// dynamically generated OG image for frame preview
-export default async function Image() {
- return new ImageResponse(
- (
-
-
{alt}
-
- ),
- {
- ...size,
- }
- );
-}
diff --git a/src/app/page.tsx b/src/app/page.tsx
index 5214b54..56d085b 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -1,22 +1,7 @@
import { Metadata } from "next";
import App from "./app";
-import { APP_URL, APP_NAME, APP_DESCRIPTION, APP_OG_IMAGE_URL, APP_ICON_URL, APP_SPLASH_URL, APP_SPLASH_BACKGROUND_COLOR, APP_BUTTON_TEXT } from "~/lib/constants";
-
-const framePreviewMetadata = {
- version: "next",
- imageUrl: APP_OG_IMAGE_URL,
- button: {
- title: APP_BUTTON_TEXT,
- action: {
- type: "launch_frame",
- name: APP_NAME,
- url: APP_URL,
- splashImageUrl: APP_SPLASH_URL,
- iconUrl: APP_ICON_URL,
- splashBackgroundColor: APP_SPLASH_BACKGROUND_COLOR,
- },
- },
-};
+import { APP_NAME, APP_DESCRIPTION, APP_OG_IMAGE_URL } from "~/lib/constants";
+import { getFrameEmbedMetadata } from "~/lib/utils";
export const revalidate = 300;
@@ -26,9 +11,10 @@ export async function generateMetadata(): Promise {
openGraph: {
title: APP_NAME,
description: APP_DESCRIPTION,
+ images: [APP_OG_IMAGE_URL],
},
other: {
- "fc:frame": JSON.stringify(framePreviewMetadata),
+ "fc:frame": JSON.stringify(getFrameEmbedMetadata()),
},
};
}
diff --git a/src/app/share/[fid]/page.tsx b/src/app/share/[fid]/page.tsx
new file mode 100644
index 0000000..bb2e823
--- /dev/null
+++ b/src/app/share/[fid]/page.tsx
@@ -0,0 +1,30 @@
+import { Metadata } from "next";
+import { redirect } from "next/navigation";
+import { APP_URL, APP_NAME, APP_DESCRIPTION } from "~/lib/constants";
+import { getFrameEmbedMetadata } from "~/lib/utils";
+export const revalidate = 300;
+
+// This is an example of how to generate a dynamically generated share page based on fid:
+// Sharing this route e.g. exmaple.com/share/123 will generate a share page for fid 123,
+// with the image dynamically generated by the opengraph-image API route.
+export async function generateMetadata({ params }: { params: { fid: string } }): Promise {
+ const fid = params.fid;
+ const imageUrl = `${APP_URL}/api/opengraph-image?fid=${fid}`;
+
+ return {
+ title: `${APP_NAME} - Share`,
+ openGraph: {
+ title: APP_NAME,
+ description: APP_DESCRIPTION,
+ images: [imageUrl],
+ },
+ other: {
+ "fc:frame": JSON.stringify(getFrameEmbedMetadata(imageUrl)),
+ },
+ };
+}
+
+export default function SharePage() {
+ // redirect to home page
+ redirect("/");
+}
\ No newline at end of file
diff --git a/src/lib/constants.ts b/src/lib/constants.ts
index 09fbd6a..d4d0168 100644
--- a/src/lib/constants.ts
+++ b/src/lib/constants.ts
@@ -6,3 +6,6 @@ export const APP_OG_IMAGE_URL = `${APP_URL}/api/opengraph-image`;
export const APP_SPLASH_URL = `${APP_URL}/splash.png`;
export const APP_SPLASH_BACKGROUND_COLOR = "#f7f7f7";
export const APP_BUTTON_TEXT = process.env.NEXT_PUBLIC_FRAME_BUTTON_TEXT;
+export const APP_WEBHOOK_URL = process.env.NEYNAR_API_KEY && process.env.NEYNAR_CLIENT_ID
+ ? `https://api.neynar.com/f/app/${process.env.NEYNAR_CLIENT_ID}/event`
+ : `${APP_URL}/api/webhook`;
diff --git a/src/lib/utils.ts b/src/lib/utils.ts
index 392cd65..3bb6c65 100644
--- a/src/lib/utils.ts
+++ b/src/lib/utils.ts
@@ -1,7 +1,7 @@
import { type ClassValue, clsx } from 'clsx';
import { twMerge } from 'tailwind-merge';
import { mnemonicToAccount } from 'viem/accounts';
-import { APP_BUTTON_TEXT, APP_ICON_URL, APP_NAME, APP_OG_IMAGE_URL, APP_SPLASH_BACKGROUND_COLOR, APP_URL } from './constants';
+import { APP_BUTTON_TEXT, APP_ICON_URL, APP_NAME, APP_OG_IMAGE_URL, APP_SPLASH_BACKGROUND_COLOR, APP_URL, APP_WEBHOOK_URL } from './constants';
import { APP_SPLASH_URL } from './constants';
interface FrameMetadata {
@@ -38,6 +38,24 @@ export function getSecretEnvVars() {
return { seedPhrase, fid };
}
+export function getFrameEmbedMetadata(ogImageUrl?: string) {
+ return {
+ version: "next",
+ imageUrl: ogImageUrl ?? APP_OG_IMAGE_URL,
+ button: {
+ title: APP_BUTTON_TEXT,
+ action: {
+ type: "launch_frame",
+ name: APP_NAME,
+ url: APP_URL,
+ splashImageUrl: APP_SPLASH_URL,
+ iconUrl: APP_ICON_URL,
+ splashBackgroundColor: APP_SPLASH_BACKGROUND_COLOR,
+ },
+ },
+ };
+}
+
export async function getFarcasterMetadata(): Promise {
// First check for FRAME_METADATA in .env and use that if it exists
if (process.env.FRAME_METADATA) {
@@ -93,13 +111,6 @@ export async function getFarcasterMetadata(): Promise {
};
}
- // Determine webhook URL based on whether Neynar is enabled
- const neynarApiKey = process.env.NEYNAR_API_KEY;
- const neynarClientId = process.env.NEYNAR_CLIENT_ID;
- const webhookUrl = neynarApiKey && neynarClientId
- ? `https://api.neynar.com/f/app/${neynarClientId}/event`
- : `${APP_URL}/api/webhook`;
-
return {
accountAssociation,
frame: {
@@ -111,7 +122,7 @@ export async function getFarcasterMetadata(): Promise {
buttonTitle: APP_BUTTON_TEXT ?? "Launch Frame",
splashImageUrl: APP_SPLASH_URL,
splashBackgroundColor: APP_SPLASH_BACKGROUND_COLOR,
- webhookUrl,
+ webhookUrl: APP_WEBHOOK_URL,
},
};
}