Skip to content

frames.js

npm install frames.js

frames.js is the fastest way to make Frames.

What's in frames.js?

  • ⚡️ Local frames debugger
  • 🥳 Write Frames using React
  • 🔋 Batteries included framework
  • 🌴 Tree-shakeable & Lightweight
  • 🚀 Library with all the functions

Quickstart

Bootstrap the project from template using the CLI tool

Run one of the commands below based on your preferred package manager and then follow the steps in the terminal.

npm
npm init frames

Alternatively, add frames.js to your existing project manually

Start with frames.js in Next.js in three steps

Add frames.js to your project

yarn add frames.js

Create your Frames app

Create a frames directory in your Next.js app and add the following files:

./app/frames/frames.ts
import { createFrames } from "frames.js/next";
 
export const frames = createFrames({
  basePath: "/frames",
});

Create a Frames route

./app/frames/route.tsx
/* eslint-disable react/jsx-key */
import { Button } from "frames.js/next";
import { frames } from "./frames";
 
const handleRequest = frames(async (ctx) => {
  return {
    image: (
      <span>
        {ctx.pressedButton
          ? `I clicked ${ctx.searchParams.value}`
          : `Click some button`}
      </span>
    ),
    buttons: [
      <Button action="post" target={{ query: { value: "Yes" } }}>
        Say Yes
      </Button>,
      <Button action="post" target={{ query: { value: "No" } }}>
        Say No
      </Button>,
    ],
  };
});
 
export const GET = handleRequest;
export const POST = handleRequest;

Include Frames alongside your existing page's metadata

./app/page.tsx
import { fetchMetadata } from "frames.js/next";
 
export async function generateMetadata() {
  return {
    title: "My Page",
    // ...
    other: {
      // ...
      ...(await fetchMetadata(
        // provide a full URL to your /frames endpoint
        new URL(
          "/frames",
          process.env.VERCEL_URL
            ? `https://{process.env.VERCEL_URL}`
            : "http://localhost:3000"
        )
      )),
    },
  };
}
 
export default function Page() {
  return <span>My existing page</span>;
}

Run yarn run dev

This will start the development server but when you open the browser you won't see anything except My existing page. This is because frames are defined as meta tags therefore you need to use some sort of a client that renders them.

Please follow our debugging guide so you can easily preview and debug your application.

Have fun! 🎉

Community

Check out the following places for more Frames-related content:

Local fully interactive Debugger & Frame validation

Or use the hosted Frames debugger. Running locally has the benefits of it working with natively with localhost.

Prefer to not use JSX?

frames.js in Next.js using helper functions

./app/page.tsx
// Page that returns a frame
import { Frame, getFrameFlattened } from "frames.js";
import type { Metadata } from "next";
 
// Declare the frame
const initialFrame: Frame = {
  image: "https://picsum.photos/seed/frames.js/1146/600",
  version: "vNext",
  buttons: [
    {
      label: "Random image",
    },
  ],
  postUrl: `${process.env.NEXT_PUBLIC_HOST}/frames`,
};
 
// Export Next.js metadata
export const metadata: Metadata = {
  title: "Random Image Frame",
  description: "This is an example of a simple frame using frames.js",
  openGraph: {
    images: [
      {
        url: "https://picsum.photos/seed/frames.js/600",
      },
    ],
  },
  other: getFrameFlattened(initialFrame),
};
./app/frames/route.ts
// Route that handles frame actions
import { getFrameHtml, validateFrameMessage } from "frames.js";
import { NextRequest } from "next/server";
 
export async function POST(request: NextRequest) {
  const body = await request.json();
 
  // Parse and validate the frame message
  const { isValid, message } = await validateFrameMessage(body);
  if (!isValid || !message) {
    return new Response("Invalid message", { status: 400 });
  }
 
  const randomInt = Math.floor(Math.random() * 100);
  const imageUrlBase = `https://picsum.photos/seed/${randomInt}`;
 
  // Use the frame message to build the frame
  const frame = {
    version: "vNext",
    image: `${imageUrlBase}/1146/600`,
    buttons: [
      {
        label: `Next (pressed by ${message.data.fid})`,
      },
    ],
    ogImage: `${imageUrlBase}/600`,
    postUrl: `${process.env.NEXT_PUBLIC_HOST}/frames`,
  };
 
  // Return the frame as HTML
  const html = getFrameHtml(frame);
 
  return new Response(html, {
    headers: {
      "Content-Type": "text/html",
    },
    status: 200,
  });
}

Source Code

The source code for frames.js is available on GitHub

frames.js is distributed under an MIT License.

We welcome contributions from the community. If you would like to contribute, please open an issue or a pull request.

Feel free to ask any questions on /frames-devs and tag @frames