Skip to content

Frog.frame Context

The c object is the parameter of the route handlers. It contains context about the current frame.

import { Frog } from 'frog'
 
export const app = new Frog({ title: 'Frog Frame' })
 
app.frame('/', (c) => {
  return c.res({/* ... */})
})

buttonIndex

  • Type: number

The index of the button that was previously clicked.

For example, if the user clicked "Banana", then buttonIndex will be 2.

import { Button, Frog } from 'frog'
 
export const app = new Frog({ title: 'Frog Frame' })
 
app.frame('/', (c) => {
  const { buttonIndex } = c
  return c.res({
    image: (
      <div style={{ color: 'white', display: 'flex', fontSize: 60 }}>
        Selected: {buttonIndex}
      </div>
    ),
    intents: [
      <Button value="apple">Apple</Button>,
      <Button value="banana">Banana</Button>,
      <Button value="mango">Mango</Button>
    ]
  })
})

buttonValue

  • Type: string

The value of the button that was previously clicked.

For example, if the user clicked "Banana", then buttonValue will be "banana".

import { Button, Frog } from 'frog'
 
export const app = new Frog({ title: 'Frog Frame' })
 
app.frame('/', (c) => {
  const { buttonValue } = c
  return c.res({
    image: (
      <div style={{ color: 'white', display: 'flex', fontSize: 60 }}>
        Selected: {buttonValue}
      </div>
    ),
    intents: [
      <Button value="apple">Apple</Button>,
      <Button value="banana">Banana</Button>,
      <Button value="mango">Mango</Button>
    ]
  })
})

deriveState

  • Type: (state: State) => void

Derives new state from the state of the previous frame.

Internally uses Immers's produce function to create a draft of the state, and then applies the changes to the state.

import { Button, Frog } from 'frog'
 
type State = {
  values: string[]
}
 
export const app = new Frog<{ State: State }>({
  initialState: {
    values: []
  }
})
 
app.frame('/', (c) => {
  const { buttonValue, deriveState } = c
  const state = deriveState(previousState => {
    if (buttonValue) previousState.values.push(buttonValue)
  })
  return c.res({
    image: (
      <div style={{ color: 'white', display: 'flex', fontSize: 60 }}>
        {state.values.map(value => <div>{value}</div>)}
      </div>
    ),
    intents: [
      <Button value="apple">Apple</Button>, 
      <Button value="banana">Banana</Button>,
      <Button value="mango">Mango</Button>,
    ]
  })
})

error

  • Type: (error: BaseError) => TypedResponse

Error response.

import { Button, Frog } from 'frog'
 
export const app = new Frog({ title: 'Frog Frame' })
 
app.frame('/', (c) => {
  return c.error({/* ... */})
})

frameData

  • Type: FrameData

Data from the frame that was passed via the POST body from a Farcaster Client. See more.

import { Button, Frog } from 'frog'
 
export const app = new Frog({ title: 'Frog Frame' })
 
app.frame('/', (c) => {
  const { frameData } = c
  const { castId, fid, messageHash, network, timestamp, url } = frameData
  return c.res({/* ... */})
})

initialPath

  • Type: string

Initial/start path of the frame set.

If the user clicks <Button.Reset>, they will be directed to this URL.

import { Button, Frog } from 'frog'
 
export const app = new Frog({ title: 'Frog Frame' })
 
app.frame('/', (c) => {
  const { initialPath } = c
  return c.res({/* ... */})
})

inputText

  • Type: string

The value of the input that was previously interacted with.

For example, if the user typed "Banana", then inputText will be "Banana".

import { Button, Frog, TextInput } from 'frog'
 
export const app = new Frog({ title: 'Frog Frame' })
 
app.frame('/', (c) => {
  const { inputText } = c
  return c.res({
    image: (
      <div style={{ color: 'white', display: 'flex', fontSize: 60 }}>
        Selected: {inputText}
      </div>
    ),
    intents: [
      <TextInput placeholder="Type your fruit..." />,
      <Button>Submit</Button>,
    ]
  })
})

previousButtonValues

  • Type: string[]

The data of the previous intents.

import { Button, Frog } from 'frog'
 
export const app = new Frog({ title: 'Frog Frame' })
 
app.frame('/', (c) => {
  return c.res({
    action: '/result',
    image: (
      <div style={{ color: 'white', display: 'flex', fontSize: 60 }}>
        Select your fruit
      </div>
    ),
    intents: [
      <Button value="apple">Apple</Button>,
      <Button value="banana">Banana</Button>,
      <Button value="mango">Mango</Button>
    ]
  })
})
 
app.frame('/result', (c) => {
  const { buttonValue, previousButtonValues } = c
  console.log(previousButtonValues)
['apple', 'banana', 'mango']
return c.res({ image: ( <div style={{ color: 'white', display: 'flex', fontSize: 60 }}> Selected: {buttonValue} </div> ), intents: [ <Button.Reset>Reset</Button.Reset>, ] }) })

previousState

  • Type: State

The state of the previous frame.

import { Button, Frog } from 'frog'
 
type State = {     
  values: string[] 
} 
 
export const app = new Frog<{ State: State }>({ 
  initialState: { 
    values: [] 
  } 
}) 
 
app.frame('/', (c) => {
  const { buttonValue, deriveState, previousState } = c
  const state = deriveState(previousState => { 
    if (buttonValue) previousState.values.push(buttonValue)
  })
  return c.res({
    image: (
      <div style={{ color: 'white', display: 'flex', fontSize: 60 }}>
        {values.map(value => <div>{value}</div>)}
      </div>
    ),
    intents: [
      <Button value="apple">Apple</Button>, 
      <Button value="banana">Banana</Button>,
      <Button value="mango">Mango</Button>,
    ]
  })
})

req

  • Type: Request

Hono request object.

import { Button, Frog } from 'frog'
 
export const app = new Frog({ title: 'Frog Frame' })
 
app.frame('/', (c) => {
  const { req } = c
  return c.res({/* ... */})
})

res

  • Type: (response: FrameResponse) => FrameResponse

The frame response.

import { Button, Frog } from 'frog'
 
export const app = new Frog({ title: 'Frog Frame' })
 
app.frame('/', (c) => {
  return c.res({/* ... */})
})

status

  • Type: "initial" | "redirect" | "response"

Status of the frame in the frame lifecycle.

  • initial - The frame has not yet been interacted with.
  • redirect - The frame interaction is a redirect (button of type 'post_redirect').
  • response - The frame has been interacted with (user presses button).
import { Button, Frog } from 'frog'
 
export const app = new Frog({ title: 'Frog Frame' })
 
app.frame('/', (c) => {
  const { status } = c
  return c.res({/* ... */})
})

transactionId

  • Type: string | undefined

The chain-specific transaction ID. Defined at the action frame of transaction route.

import { Button, Frog } from 'frog'
 
export const app = new Frog({ title: 'Frog Frame' })
 
app.frame('/', (c) => {
  return c.res({
    action: '/finish',
    image: (
      <div style={{ color: 'white', display: 'flex', fontSize: 60 }}>
        Perform a transaction
      </div>
    ),
    intents: [
      <TextInput placeholder="Value (ETH)" />,
      <Button.Transaction target="/send-ether">Send Ether</Button.Transaction>,
    ]
  })
})
 
app.frame('/finish', (c) => {
  const { transactionId } = c
  return c.res({
    image: (
      <div style={{ color: 'white', display: 'flex', fontSize: 60 }}>
        Transaction ID: {transactionId}
      </div>
    )
  })
})

var

  • Type: HonoContext['var']

Extract a context value that was previously set via set in Middleware.

import { Button, Frog } from 'frog'
 
export const app = new Frog({ title: 'Frog Frame' })
 
app.use(async (c, next) => {
  c.set('message', 'Frog is cool!!')
  await next()
})
 
app.frame('/', (c) => {
  const message = c.var.message
  return c.res({/* ... */})
})

verified

  • Type: boolean

Whether or not the frameData (and buttonIndex, buttonValue, inputText) was verified by the Farcaster Hub API.

import { Button, Frog } from 'frog'
 
export const app = new Frog({ title: 'Frog Frame' })
 
app.frame('/', (c) => {
  const { verified } = c
  return c.res({/* ... */})
})

url

  • Type: string

URL of the frame.

import { Button, Frog } from 'frog'
 
export const app = new Frog({ title: 'Frog Frame' })
 
app.frame('/', (c) => {
  const { url } = c
  return c.res({/* ... */})
})