Skip to content

Quickstart Guide: Display Frames

This guide shows you how to add frames rendering to your next.js + tailwind app using frames.js.

Steps

Create a new repo

Create a new Next.js app

npx create-next-app@latest my-project --ts --eslint --tailwind --app
cd my-project

Add @frames.js/render to your project

yarn add @frames.js/render

Add proxies for routing frame requests via your backend for privacy + preventing CORS issues

./app/frames/route.tsx
export { GET, POST } from "@frames.js/render/next";

Add the renderer to your page

./app/page.tsx
"use client";
import {
  FrameUI,
  fallbackFrameContext,
  FrameContext,
} from "@frames.js/render";
import { signFrameAction, FarcasterSigner } from '@frames.js/render/farcaster'
import { FrameImageNext } from "@frames.js/render/next";
import { FrameButton } from "frames.js";
import { useFrame } from "@frames.js/render/use-frame";
 
export default function Page() {
  // TODO: replace with your farcaster signer
  const farcasterSigner: FarcasterSigner = {
    fid: 1,
    status: 'approved',
    publicKey:
      "0x00000000000000000000000000000000000000000000000000000000000000000",
    privateKey:
      "0x00000000000000000000000000000000000000000000000000000000000000000",
  };
  
  const frameState = useFrame({
    // replace with your frame url
    homeframeUrl:
      "https://fc-polls.vercel.app/polls/73c6efda-bae7-4d46-8f36-3bb3b8377448",
    // corresponds to the name of the route for POST in step 3
    frameActionProxy: "/frames",
    connectedAddress: undefined,
    // corresponds to the name of the route for GET in step 3
    frameGetProxy: "/frames",
    frameContext: fallbackFrameContext,
    // map to your identity if you have one
    signerState: {
      hasSigner: farcasterSigner !== undefined,
      signer: farcasterSigner,
      onSignerlessFramePress: () => {
        // Only run if `hasSigner` is set to `false`
        // This is a good place to throw an error or prompt the user to login
        alert("A frame button was pressed without a signer. Perhaps you want to prompt a login");
      },
      signFrameAction: signFrameAction,
    },
  });
 
  return (
    <div className="w-[400px]">
      <FrameUI frameState={frameState} theme={{}} FrameImage={FrameImageNext} />
    </div>
  );
}
 

In order for the styles to work, your project should have tailwind set up as well as the tailwind.config.js rule

tailwind.config.js
const config = {
    // ...
    content: [
      "./app/*.{ts,tsx,js,css}",
      "./app/**/*.{ts,tsx,js,css}",
      "./node_modules/@frames.js/render/dist/*.{ts,tsx,js,css}",
      "./node_modules/@frames.js/render/dist/**/*.{ts,tsx,js,css}",
      // ...
    ]
}

Allow images from any domain

next.config.js
const nextConfig = {
  images: {
    remotePatterns: [
      {
        protocol: "https",
        hostname: "**",
      },
    ],
  },
};

Run yarn run dev

Done! 🎉

Optional

If needed, you can implement FrameUI yourself, using the FrameUI component as a template