Open Frames: make frames that work everywhere
Open Frames is a standard for Frames that work in multiple ecosystems, including Farcaster, XMTP, Lens and others.
You can define your frame as supporting multiple Open Frames compatible protocols by using the openframes
middleware.
// ...
import { openframes } from "frames.js/middleware";
const frames = createFrames({
// ...
middleware: [
openframes({
clientProtocol: {
id: "my-protocol",
version: "1.0.0",
},
handler: {
isValidPayload: (body: JSON) => {
// Check if the request body is a valid Open Frames action
// ...
return isValid; // true or false
},
getFrameMessage: async (body: JSON) => {
// Parse the data in the request body and return a Frame message
// ...
return frameMessage; // { username: "alice" }
},
},
}),
],
});
and access the protocol used to sign the Frame Message via the clientProtocol
property of the context.
// ...
const handleRequest = frames(async (ctx) => {
if (ctx.clientProtocol === "my-protocol") {
// ctx.username is available here
}
// ...
});
Unauthenticated Frames
Open Frames can be used to create unauthenticated Frames that can be supported by all clients by using the anonymous frames convention, which is built into the openframes middleware.
In order to support unauthenticated frames in your application, simply include openframes()
without supplying any arguments in your createFrames
middleware.
const frames = createFrames({
// ...
middleware: [openframes()],
});
This will add of:accepts:anonymous
to your page metadata. Clients will then be able to send frame POST requests to your handler without needing to sign the payload. Your frames
handler will receive the buttonIndex
and optionally inputText
and state
in the ctx
object.
Multi Protocol Example
Here is an example of a multi-protocol createFrames configuration that supports anonymous, XMTP, and Lens protocols.
import { createFrames } from "frames.js/next";
import { openframes } from "frames.js/middleware";
import { getXmtpFrameMessage, isXmtpFrameActionPayload } from "frames.js/xmtp";
import { getLensFrameMessage, isLensFrameActionPayload } from "frames.js/lens";
export const frames = createFrames({
// ...
middleware: [
// XMTP
openframes({
clientProtocol: {
id: "xmtp",
version: "2024-02-09",
},
handler: {
isValidPayload: (body) => isXmtpFrameActionPayload(body),
getFrameMessage: async (body) => {
if (!isXmtpFrameActionPayload(body)) {
return undefined;
}
const result = await getXmtpFrameMessage(body);
return result;
},
},
}),
// Lens
openframes({
clientProtocol: {
id: "lens",
version: "1.0.0",
},
handler: {
isValidPayload: (body) => isLensFrameActionPayload(body),
getFrameMessage: async (body) => {
if (!isLensFrameActionPayload(body)) {
return undefined;
}
const result = await getLensFrameMessage(body);
return result;
},
},
}),
// Anonymous
openframes(),
],
});
See the full example in the Multi Protocol starter template.