Middleware
Frames.js uses middleware to extend the functionality of Frames, bringing in data from API providers, verifying frame actions and adding Open Frames support.
You can use middleware for all your frames by passing in middleware via the middleware
option in createFrames
or you can specify per-route middleware.
Using middleware
Include the middleware in your createFrames
call:
import { farcasterHubContext } from "frames.js/middleware";
import { createFrames } from "frames.js/next";
const frames = createFrames({
basePath: "/",
initialState: {
pageIndex: 0,
},
middleware: [farcasterHubContext()],
});
import { frames } from "./frames";
export const POST = frames(async (ctx) => {
// The added context from the middleware will be available on `ctx` here
if (!ctx.message.isValid) {
throw new Error("Invalid message");
}
return {
image: (
<div tw="flex">
The user's username is {ctx.message.requesterUserData.username}
</div>
),
};
});
Per-route middleware
You can also specify middleware per-route that will only be applied to that route:
import { farcasterHubContext } from "frames.js/middleware";
export const POST = frames(
async (ctx) => {
// The added context from the middleware will be available on `ctx` here
if (!ctx.message.isValid) {
throw new Error("Invalid message");
}
return {
image: (
<div>
The user's username is {ctx.message.requesterUserData.username}
</div>
),
};
},
{
middleware: [farcasterHubContext()],
}
);
Defining your own middleware
You can define your own middleware by creating a function that returns a promise that resolves to the next middleware, or a Web API Response
, or a FrameDefinition
.
Middleware can modify the context or return a response that will terminate the request early.
Adding context
import { createFrames, types } from "frames.js/next";
const myMiddleware: types.FramesMiddleware<any, { foo: string }> = async (
ctx,
next
) => {
return next({ foo: "bar" });
};
export const frames = createFrames({
basePath: "/",
initialState: {
pageIndex: 0,
},
// Add the middleware
middleware: [myMiddleware],
});
Accessing the request object
Sometimes you want to access the request object in your middleware - whenever you do this, you should clone the request object to avoid mutating it and breaking other middleware.
Here's an example of creating middleware which will add the request json to your context:
import { createFrames, types } from "frames.js/next";
const bodyMiddleware: types.FramesMiddleware<any, { body: any }> = async (
ctx,
next
) => {
const body = await ctx.request.clone().json();
return next({ body });
};
export const frames = createFrames({
basePath: "/",
initialState: {
pageIndex: 0,
},
middleware: [bodyMiddleware],
// The request body will now be available via `ctx.body` in your frame handlers
});