Skip to content

silverdoor-ai/frames.js

 
 

Repository files navigation

frames.js

frames.js is a TypeScript library and framework for writing and testing Farcaster Frames.

Features

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

Documentation

Look at our documentation to learn more about frames.js.

Installation

npm install frames.js
yarn add frames.js

Quick Start

Start with frames.js in Next.js in two copy-pastes

// ./app/page.tsx

import {
  FrameContainer,
  FrameImage,
  FrameButton,
  useFramesReducer,
  getPreviousFrame,
  validateActionSignature,
  FrameInput,
} from "frames.js/next/server";

const reducer = (state, action) => ({ count: state.count + 1 });

export default async function Home(props) {
  const previousFrame = getPreviousFrame(props.searchParams);
  await validateActionSignature(previousFrame.postBody);
  const [state, dispatch] = useFramesReducer(
    reducer,
    { count: 0 },
    previousFrame
  );

  return (
    <FrameContainer
      postUrl="/frames"
      state={state}
      previousFrame={previousFrame}
    >
      <FrameImage src="https://picsum.photos/seed/frames.js/1146/600" />
      <FrameButton onClick={dispatch}>{state.count}</FrameButton>
    </FrameContainer>
  );
}
// ./app/frames/route.ts

export { POST } from "frames.js/next/server";

Alternatively, Fork our boilerplate that includes local debugging

Local fully interactive Debugger & Frame validation

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

Prefer to not use JSX?

Use frames.js in Next.js using helper functions

// page that renders a frame
// ./app/page.tsx

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),
};
// handle frame actions
// ./app/frames/route.ts

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,
  });
}

License

Distributed under an MIT License. See LICENSE for more information.

Community

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

About

The fastest way to make a Farcaster Frame

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • TypeScript 96.4%
  • JavaScript 3.6%