From 681f287c20f620944770742e21471f66530a9f9e Mon Sep 17 00:00:00 2001 From: veganbeef Date: Fri, 9 May 2025 10:55:22 -0700 Subject: [PATCH] feat: neynar data in opengraph share image --- package.json | 2 +- scripts/build.js | 2 +- scripts/deploy.js | 2 +- src/app/api/opengraph-image/route.tsx | 30 +++++++++++++++++++++++++++ src/lib/constants.ts | 4 ++-- src/lib/neynar.ts | 15 +++++++++++++- 6 files changed, 49 insertions(+), 6 deletions(-) create mode 100644 src/app/api/opengraph-image/route.tsx diff --git a/package.json b/package.json index 4dba629..88e56ce 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@neynar/create-farcaster-mini-app", - "version": "1.2.21", + "version": "1.2.22", "type": "module", "private": false, "access": "public", diff --git a/scripts/build.js b/scripts/build.js index e00c77c..9d98ba1 100755 --- a/scripts/build.js +++ b/scripts/build.js @@ -172,7 +172,7 @@ async function generateFarcasterMetadata(domain, fid, accountAddress, seedPhrase name: process.env.NEXT_PUBLIC_FRAME_NAME, iconUrl: `https://${domain}/icon.png`, homeUrl: `https://${domain}`, - imageUrl: `https://${domain}/opengraph-image`, + imageUrl: `https://${domain}/api/opengraph-image`, buttonTitle: process.env.NEXT_PUBLIC_FRAME_BUTTON_TEXT, splashImageUrl: `https://${domain}/splash.png`, splashBackgroundColor: "#f7f7f7", diff --git a/scripts/deploy.js b/scripts/deploy.js index 4f60879..b5bbabd 100755 --- a/scripts/deploy.js +++ b/scripts/deploy.js @@ -83,7 +83,7 @@ async function generateFarcasterMetadata(domain, fid, accountAddress, seedPhrase name: process.env.NEXT_PUBLIC_FRAME_NAME?.trim(), iconUrl: `https://${trimmedDomain}/icon.png`, homeUrl: `https://${trimmedDomain}`, - imageUrl: `https://${trimmedDomain}/opengraph-image`, + imageUrl: `https://${trimmedDomain}/api/opengraph-image`, buttonTitle: process.env.NEXT_PUBLIC_FRAME_BUTTON_TEXT?.trim(), splashImageUrl: `https://${trimmedDomain}/splash.png`, splashBackgroundColor: "#f7f7f7", diff --git a/src/app/api/opengraph-image/route.tsx b/src/app/api/opengraph-image/route.tsx new file mode 100644 index 0000000..37aa1e8 --- /dev/null +++ b/src/app/api/opengraph-image/route.tsx @@ -0,0 +1,30 @@ +import { ImageResponse } from "next/og"; +import { NextRequest } from "next/server"; +import { getNeynarUser } from "~/lib/neynar"; + +export const dynamic = 'force-dynamic'; + +export async function GET(request: NextRequest) { + const { searchParams } = new URL(request.url); + const fid = searchParams.get('fid'); + + const user = await getNeynarUser(Number(fid)); + + return new ImageResponse( + ( +
+ {user?.pfp_url && ( +
+ Profile +
+ )} +

{user?.display_name ? `Hello from ${user.display_name ?? user.username}!` : 'Hello!'}

+

Powered by Neynar 🪐

+
+ ), + { + width: 1200, + height: 800, + } + ); +} \ No newline at end of file diff --git a/src/lib/constants.ts b/src/lib/constants.ts index 201983c..09fbd6a 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -1,8 +1,8 @@ -export const APP_URL = process.env.NEXT_PUBLIC_URL; +export const APP_URL = process.env.NEXT_PUBLIC_URL!; export const APP_NAME = process.env.NEXT_PUBLIC_FRAME_NAME; export const APP_DESCRIPTION = process.env.NEXT_PUBLIC_FRAME_DESCRIPTION; export const APP_ICON_URL = `${APP_URL}/icon.png`; -export const APP_OG_IMAGE_URL = `${APP_URL}/opengraph-image`; +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; diff --git a/src/lib/neynar.ts b/src/lib/neynar.ts index 44fbb5f..ee40213 100644 --- a/src/lib/neynar.ts +++ b/src/lib/neynar.ts @@ -1,4 +1,4 @@ -import { NeynarAPIClient, Configuration } from '@neynar/nodejs-sdk'; +import { NeynarAPIClient, Configuration, WebhookUserCreated } from '@neynar/nodejs-sdk'; import { APP_URL } from './constants'; let neynarClient: NeynarAPIClient | null = null; @@ -18,6 +18,19 @@ export function getNeynarClient() { return neynarClient; } +type User = WebhookUserCreated['data']; + +export async function getNeynarUser(fid: number): Promise { + try { + const client = getNeynarClient(); + const usersResponse = await client.fetchBulkUsers({ fids: [fid] }); + return usersResponse.users[0]; + } catch (error) { + console.error('Error getting Neynar user:', error); + return null; + } +} + type SendFrameNotificationResult = | { state: "error";