mirror of
https://github.com/neynarxyz/create-farcaster-mini-app.git
synced 2025-11-16 08:08:56 -05:00
fix: dynamic share page
This commit is contained in:
parent
681f287c20
commit
08091fc206
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@neynar/create-farcaster-mini-app",
|
"name": "@neynar/create-farcaster-mini-app",
|
||||||
"version": "1.2.22",
|
"version": "1.2.23",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"private": false,
|
"private": false,
|
||||||
"access": "public",
|
"access": "public",
|
||||||
|
|||||||
@ -8,7 +8,7 @@ export async function GET(request: NextRequest) {
|
|||||||
const { searchParams } = new URL(request.url);
|
const { searchParams } = new URL(request.url);
|
||||||
const fid = searchParams.get('fid');
|
const fid = searchParams.get('fid');
|
||||||
|
|
||||||
const user = await getNeynarUser(Number(fid));
|
const user = fid ? await getNeynarUser(Number(fid)) : null;
|
||||||
|
|
||||||
return new ImageResponse(
|
return new ImageResponse(
|
||||||
(
|
(
|
||||||
|
|||||||
@ -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(
|
|
||||||
(
|
|
||||||
<div tw="h-full w-full flex flex-col justify-center items-center relative bg-white">
|
|
||||||
<h1 tw="text-6xl">{alt}</h1>
|
|
||||||
</div>
|
|
||||||
),
|
|
||||||
{
|
|
||||||
...size,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -1,22 +1,7 @@
|
|||||||
import { Metadata } from "next";
|
import { Metadata } from "next";
|
||||||
import App from "./app";
|
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";
|
import { APP_NAME, APP_DESCRIPTION, APP_OG_IMAGE_URL } from "~/lib/constants";
|
||||||
|
import { getFrameEmbedMetadata } from "~/lib/utils";
|
||||||
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,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export const revalidate = 300;
|
export const revalidate = 300;
|
||||||
|
|
||||||
@ -26,9 +11,10 @@ export async function generateMetadata(): Promise<Metadata> {
|
|||||||
openGraph: {
|
openGraph: {
|
||||||
title: APP_NAME,
|
title: APP_NAME,
|
||||||
description: APP_DESCRIPTION,
|
description: APP_DESCRIPTION,
|
||||||
|
images: [APP_OG_IMAGE_URL],
|
||||||
},
|
},
|
||||||
other: {
|
other: {
|
||||||
"fc:frame": JSON.stringify(framePreviewMetadata),
|
"fc:frame": JSON.stringify(getFrameEmbedMetadata()),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
30
src/app/share/[fid]/page.tsx
Normal file
30
src/app/share/[fid]/page.tsx
Normal file
@ -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<Metadata> {
|
||||||
|
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("/");
|
||||||
|
}
|
||||||
@ -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_URL = `${APP_URL}/splash.png`;
|
||||||
export const APP_SPLASH_BACKGROUND_COLOR = "#f7f7f7";
|
export const APP_SPLASH_BACKGROUND_COLOR = "#f7f7f7";
|
||||||
export const APP_BUTTON_TEXT = process.env.NEXT_PUBLIC_FRAME_BUTTON_TEXT;
|
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`;
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { type ClassValue, clsx } from 'clsx';
|
import { type ClassValue, clsx } from 'clsx';
|
||||||
import { twMerge } from 'tailwind-merge';
|
import { twMerge } from 'tailwind-merge';
|
||||||
import { mnemonicToAccount } from 'viem/accounts';
|
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';
|
import { APP_SPLASH_URL } from './constants';
|
||||||
|
|
||||||
interface FrameMetadata {
|
interface FrameMetadata {
|
||||||
@ -38,6 +38,24 @@ export function getSecretEnvVars() {
|
|||||||
return { seedPhrase, fid };
|
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<FrameMetadata> {
|
export async function getFarcasterMetadata(): Promise<FrameMetadata> {
|
||||||
// First check for FRAME_METADATA in .env and use that if it exists
|
// First check for FRAME_METADATA in .env and use that if it exists
|
||||||
if (process.env.FRAME_METADATA) {
|
if (process.env.FRAME_METADATA) {
|
||||||
@ -93,13 +111,6 @@ export async function getFarcasterMetadata(): Promise<FrameMetadata> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 {
|
return {
|
||||||
accountAssociation,
|
accountAssociation,
|
||||||
frame: {
|
frame: {
|
||||||
@ -111,7 +122,7 @@ export async function getFarcasterMetadata(): Promise<FrameMetadata> {
|
|||||||
buttonTitle: APP_BUTTON_TEXT ?? "Launch Frame",
|
buttonTitle: APP_BUTTON_TEXT ?? "Launch Frame",
|
||||||
splashImageUrl: APP_SPLASH_URL,
|
splashImageUrl: APP_SPLASH_URL,
|
||||||
splashBackgroundColor: APP_SPLASH_BACKGROUND_COLOR,
|
splashBackgroundColor: APP_SPLASH_BACKGROUND_COLOR,
|
||||||
webhookUrl,
|
webhookUrl: APP_WEBHOOK_URL,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user