# Frames v2 Research [We're dogfooding v2 frames at Merkle and making them open source.](https://warpcast.com/dwr.eth/0xcafbc039) ## Horsefacts ### [Farcaster frames v2 demo app walkthrough](https://www.youtube.com/watch?v=5wAbo_YsuC4) - [frames-v2-demo](https://github.com/farcasterxyz/frames-v2-demo) - [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/) #### Load SDK Client side only package that requires access to Window ```tsx import sdk, { FrameNotificationDetails, type FrameContext, } from "@farcaster/frame-sdk"; ``` ![image](https://hackmd.io/_uploads/rk_F8Cw4yl.png) #### Call SDK Actions Ready ```tsx useEffect(() => { const load = async () => { setContext(await sdk.context); sdk.actions.ready({}); }; if (sdk && !isSDKLoaded) { setIsSDKLoaded(true); load(); } }, [isSDKLoaded]); ``` #### Call SDK Actions (to interact with Farcaster client) ![image](https://hackmd.io/_uploads/rJQw1CvEkl.png) ```tsx const openUrl = useCallback(() => { sdk.actions.openUrl("https://www.youtube.com/watch?v=dQw4w9WgXcQ"); }, []); ``` ```html <Button onClick={openUrl}>Open Link</Button> ``` #### Use Provider to Interact With Wallet wagmi and/or viem React hooks ```tsx import { useAccount, useSendTransaction, useSignMessage, useSignTypedData, useWaitForTransactionReceipt, useDisconnect, useConnect, useSwitchChain, useChainId, } from "wagmi"; ``` ```tsx const { sendTransaction, error: sendTxError, isError: isSendTxError, isPending: isSendTxPending, } = useSendTransaction(); ``` ```tsx const { sendTransaction, data, error: sendTxError, isError: isSendTxError, isPending: isSendTxPending, } = useSendTransaction(); ``` --- `layout.tsx` Entrypoint to the app ```tsx import "~/app/globals.css"; ``` ```tsx export const metadata: Metadata = { title: "Farcaster Frames v2 Demo", description: "A Farcaster Frames v2 demo app", }; ``` --- `providers.tsx` ```tsx import dynamic from "next/dynamic"; ``` --- `WagmiProvider.tsx` ```tsx export const config = createConfig({ chains: [base, optimism], transports: { [base.id]: http(), [optimism.id]: http(), }, connectors: [frameConnector()], }); ``` `frameConnector` is the Farcaster magic --- `connector.ts` They are adding this to the SDK --- `page.tsx` --- Tunnels, Next.js, React hooks, metadata and web standards was able to have a fuctional frame in a day and teach a workshop to devs. spent 4 hours and don't even have the demo app running locally Does this lock us into Vercel? What can we do to strip it down? Make sure to do the dynamic imports correctly ### [Farcaster Frames v2: Dev Tools, App Manifest, Account Association, Embeds](https://www.youtube.com/watch?v=S1KuwHYPtxU) #### Developer Mode ##### Frames ##### Domains `proposals.farcastle.net` Can put this in the API route or a static file. What is the benefit of dynamically generating the `appUrl` in `route.ts`? `/.well-known/farcaster.json` ```json { "accountAssociation": { "header": "eyJmaWQiOjUwMzcsInR5cGUiOiJjdXN0b2R5Iiwia2V5IjoiMHhGNWIzZGU5MTU5NEU3OGMyMUQ3NmEwOTllOTZFMDVBNDI1MkIyNWE5In0", "payload": "eyJkb21haW4iOiJwcm9wb3NhbHMuZmFyY2FzdGxlLm5ldCJ9", "signature": "MHg5N2JmMGJjMWViNzYzZTg0MmNiNmRiOTRlY2Y2OGJiNDFiNDQwNjZiNzA4Y2YzZjczMGQwMWYxM2EwMzcyODkwM2JjYjljM2NlNjY5Y2RmOGNmNmI3MWJiYjY4ZTg1ODg3MDU5ZWE1MjhhOGFjZmExOWJmYmE4MzkyYzlmNGY0ZTFj" }, "frame": { "name": "Example Frame", "version": "0.0.1", "iconUrl": "https://example.com/icon.png", "homeUrl": "https://example.com", "splashImageUrl": "https://example.com/splash.png", "splashBackgroundColor": "#eeccff", "webhookUrl": "https://example.com/webhook" } } ``` ![image](https://hackmd.io/_uploads/SycDzy_Ekg.png) Header will contain the domain and the account that signed it as attribution. #### Frame Embeds Inject metatags into the header of the app `imageUrl` can dynamically generate an image in `opengraph-image.tsx` or serve a static image :point_down: `title` is where the text on the button is defined ```tsx const frame = { version: "next", imageUrl: `${appUrl}/opengraph-image`, button: { title: "Launch Frame", action: { type: "launch_frame", name: "Farcaster Frames v2 Demo", url: appUrl, splashImageUrl: `${appUrl}/splash.png`, splashBackgroundColor: "#f7f7f7", }, }, }; ``` ```tsx export async function generateMetadata(): Promise<Metadata> { return { title: "Farcaster Frames v2 Demo", openGraph: { title: "Farcaster Frames v2 Demo", description: "A Farcaster Frames v2 demo app.", }, other: { "fc:frame": JSON.stringify(frame), }, }; } ```