Skip to content

Middleware

Since Frog is built on top of Hono, Frog supports Hono's middleware pattern.

Middleware works before and after the .frame handler by allowing you to manipulate the request and response before and after dispatching respectively. We recommend checking out the Hono documentation on Middleware for a more in-depth understanding.

Built-in Middlewares

Neynar

Frog comes with a built-in middleware for Neynar which allows you to easily integrate Neynar features (such as the interactor of your frame, and frame cast) into Frog context.

/** @jsxImportSource frog/jsx */
// ---cut---
import { Button, Frog } from 'frog'
import { type NeynarVariables, neynar } from 'frog/middlewares'
 
export const app = new Frog<{ 
  Variables: NeynarVariables 
// @log:   ↑ 1. Inject variables to get type inference on context (`c.var`).
}>()
 
// @log:     ↓ 2. Inject `neynar` middleware onto the app.
app.use(
  neynar({
    apiKey: 'NEYNAR_FROG_FM',
    features: ['interactor', 'cast'],
  }),
)
 
app.frame('/', (c) => {
// @log:   ↓ 3. Use `c.var` to access Neynar variables!
  const { displayName, followerCount } = c.var.interactor || {}
  console.log('cast: ', c.var.cast)
  console.log('interactor: ', c.var.interactor)
  //                                ^?
  return c.res({
    image: (
      <div
        style={{
          alignItems: 'center',
          color: 'white',
          display: 'flex',
          justifyContent: 'center',
          fontSize: 48,
          height: '100%',
          width: '100%',
        }}
      >
        Greetings {displayName}, you have {followerCount} followers.
      </div>
    ),
  })
})
## Errors were thrown in the sample, but not included in an error tag These errors were not marked as being expected: 2307 2339. Expected: // @errors: 2307 2339 Compiler Errors: index.tsx [2307] 127 - Cannot find module 'frog/middlewares' or its corresponding type declarations. [2339] 570 - Property 'var' does not exist on type '{ buttonIndex?: 2 | 1 | 3 | 4 | undefined; buttonValue?: string | undefined; frameData?: { buttonIndex?: 2 | 1 | 3 | 4 | undefined; castId: { fid: number; hash: string; }; fid: number; inputText?: string | undefined; ... 5 more ...; url: string; } | undefined; ... 12 more ...; transactionId?: string | undefined; }'. [2339] 617 - Property 'var' does not exist on type '{ buttonIndex?: 2 | 1 | 3 | 4 | undefined; buttonValue?: string | undefined; frameData?: { buttonIndex?: 2 | 1 | 3 | 4 | undefined; castId: { fid: number; hash: string; }; fid: number; inputText?: string | undefined; ... 5 more ...; url: string; } | undefined; ... 12 more ...; transactionId?: string | undefined; }'. [2339] 659 - Property 'var' does not exist on type '{ buttonIndex?: 2 | 1 | 3 | 4 | undefined; buttonValue?: string | undefined; frameData?: { buttonIndex?: 2 | 1 | 3 | 4 | undefined; castId: { fid: number; hash: string; }; fid: number; inputText?: string | undefined; ... 5 more ...; url: string; } | undefined; ... 12 more ...; transactionId?: string | undefined; }'.

Custom Middleware

You can write your own Frog middleware. This is great if you want to share common logic across or frames or if you are developing a SDK for Frog users to hook into their frames.

import { Frog } from 'frog'
 
export const app = new Frog()
 
// Custom logger
app.use(async (c, next) => {
  console.log(`[${c.req.method}] ${c.req.url}`)
  await next()
})
 
// Add a custom header
app.use('/foo/*', async (c, next) => {
  await next()
  c.header('x-message', 'Only called for `/foo` and `/foo/bar` frames.')
})
 
app.frame('/', (c) => {/* ... */})
 
app.frame('/foo', (c) => {/* ... */})
 
app.frame('/foo/bar', (c) => {/* ... */})

Community Middleware

Middleware is one of the most powerful pieces of Frog. This section showcases community-built middleware that you can use in your Frog apps.

If you've built a middleware for Frog, feel free to submit a PR to add it to this list.

Pinata FDK Analytics Middleware

The Frog Analytics Plugin allows you to hook into Pinata Frame analytics.

import { PinataFDK } from 'pinata-fdk'
 
const app = new Frog()
 
const fdk = new PinataFDK({
  pinata_jwt: '<YOUR_PINATA_JWT>',
  pinata_gateway: '<YOUR_PINATA_GATEWAY>'
})
 
app.use('/', fdk.analyticsMiddleware({
  frameId: 'my-frame-id',
  customId: 'my-custom-id',
}))