Skip to content

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

Clone the frames.js starter template (with local debugger)

Run to clone the starter into a new folder called framesjs-starter

npx degit github:framesjs/frames.js/examples/framesjs-starter#main framesjs-starter

or clone from github

Alternatively, add frames.js to your existing project manually

1. Add frames.js to your project

yarn add frames.js

2. 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";exportconstframes=createFrames({basePath: "/frames",});

3. Create a Frames route

./app/frames/route.tsx

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

4. Include Frames alongside your existing page's metadata

import{fetchMetadata}from"frames.js/next";exportasyncfunctiongenerateMetadata(){return{title: "My Page",// ...other: {// ...
...(awaitfetchMetadata(// provide a full URL to your /frames endpointnewURL("/frames",process.env.VERCEL_URL
? `https://${process.env.VERCEL_URL}`
: "http://localhost:3000"))),},};}exportdefaultfunctionPage(){return<span>My existing page</span>;}

5. Done! 🎉

Debugging your Frames locally

Prefer not to use a Framework?

You can use frames.js library helper functions instead

// page that renders a frame// ./app/page.tsximport{Frame,getFrameFlattened}from"frames.js";importtype{Metadata}from"next";// Declare the frameconstinitialFrame: 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 metadataexportconstmetadata: 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.tsimport{getFrameHtml,validateFrameMessage}from"frames.js";import{NextRequest}from"next/server";exportasyncfunctionPOST(request: NextRequest){constbody=awaitrequest.json();// Parse and validate the frame messageconst{ isValid, message }=awaitvalidateFrameMessage(body);if(!isValid||!message){returnnewResponse("Invalid message",{status: 400});}constrandomInt=Math.floor(Math.random()*100);constimageUrlBase=`https://picsum.photos/seed/${randomInt}`;// Use the frame message to build the frameconstframe={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 HTMLconsthtml=getFrameHtml(frame);returnnewResponse(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 Frames

Topics

Resources

Contributing

Stars

384 stars

Watchers

5 watching

Forks

Releases

Packages

Used by

Contributors

Languages