Skip to content

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:

frames.ts
import { farcasterHubContext } from "frames.js/middleware";
import { createFrames } from "frames.js/next";
 
const frames = createFrames({
  basePath: "/",
  initialState: {
    pageIndex: 0,
  },
  middleware: [farcasterHubContext()],
});
frames/username/route.tsx
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:

frames/username/route.tsx
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

frames.ts
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
});