Skip to content

Images & Intents

Farcaster Frames have two main UI components:

  • an Image, and
  • a set of Intents

Images & Intents

Image

In Farcaster Frames, an Image behaves similarly to an Open Graph image, and shares the same constraints.

Frog uses Satori & Resvg under-the-hood to compile JSX elements to a static image. Check out Vercel's Open Graph Image Generation page to learn more about the internals of Frog's image renderer, and the constraints and best practices for creating OG images.

In Frog, an Image can be rendered via the image return property:

src/index.tsx
import { Button, Frog } from 'frog'
 
export const app = new Frog()
 
app.frame('/', (c) => {
  const { buttonValue, status } = c
  return c.res({
    image: (
      <div style={{ color: 'white', display: 'flex', fontSize: 60 }}>
        {status === 'initial' ? (
          'Select your fruit!'
        ) : (
          `Selected: ${buttonValue}`
        )}
      </div>
    ),
    intents: [
      <Button value="apple">Apple</Button>,
      <Button value="banana">Banana</Button>,
      <Button value="mango">Mango</Button>
    ]
  })
})

You can also specify an image URL:

src/index.tsx
import { Button, Frog } from 'frog'
 
export const app = new Frog()
 
app.frame('/', (c) => {
  const { buttonValue, status } = c
  return c.res({
    image: 'https://i.ytimg.com/vi/R3UACX5eULI/maxresdefault.jpg',
    intents: [
      <Button value="apple">Apple</Button>,
      <Button value="banana">Banana</Button>,
      <Button value="mango">Mango</Button>
    ]
  })
})

Image Options

Frog also exposes options that you can use to customize the image.

src/index.tsx
app.frame('/', (c) => {
  const { buttonValue, status } = c
  return c.res({
    image: (
      <div style={{ color: 'white', display: 'flex', fontSize: 60 }}>
        {status === 'initial' ? (
          'Select your fruit!'
        ) : (
          `Selected: ${buttonValue}`
        )}
      </div>
    ),
    imageOptions: { width: 600, height: 600 },
    intents: [
      <Button value="apple">Apple</Button>,
      <Button value="banana">Banana</Button>,
      <Button value="mango">Mango</Button>
    ]
  })
})

You can also pass a set of default options to the Frog constructor:

src/index.tsx
import { Button, Frog } from 'frog'
 
export const app = new Frog({
  imageOptions: { height: 600, width: 600 }
})
PropertyTypeDefaultDescription
widthnumber1200The width of the image.
heightnumber630The height of the image.
emoji"twemoji" "blobmoji" "noto" "openmoji"The emoji set to use.
debugbooleanfalseDebug mode flag.
fontsFont[]The fonts to use.
headersHeadersInitHeaders for the image response.

Read more on Image Options.

Intents

Intents are the interactive elements in a Farcaster Frame. They are the buttons and/or text inputs that users can interact with.

Frog currently supports the following Intents:

In Frog, Intents are rendered via the intent return property:

src/index.tsx
/** @jsxImportSource frog/jsx */
// ---cut---
import { Button, Frog, TextInput } from 'frog' // [!code focus]
 
export const app = new Frog()
 
app.frame('/', (c) => {
  const { buttonValue, inputText, status } = c
  const fruit = inputText || buttonValue
  return c.res({
    image: (
      <div style={{ color: 'white', display: 'flex', fontSize: 60 }}>
        {status === 'initial' ? (
          'Select your fruit!'
        ) : (
          `Selected: ${fruit}`
        )}
      </div>
    ),
    intents: [
      <TextInput placeholder="Enter a custom fruit..." />,
      <Button value="apple">Apple</Button>,
      <Button value="banana">Banana</Button>,
      <Button value="mango">Mango</Button>
    ]
  })
})
## Errors were thrown in the sample, but not included in an error tag These errors were not marked as being expected: 2786. Expected: // @errors: 2786 Compiler Errors: index.tsx [2786] 536 - 'TextInput' cannot be used as a JSX component. Its type 'typeof TextInput' is not a valid JSX element type. Type 'typeof TextInput' is not assignable to type '(props: any, deprecatedLegacyContext?: any) => ReactNode'. Type 'Element' is not assignable to type 'ReactNode'. Type 'Promise<HtmlEscapedString>' is not assignable to type 'ReactNode'.