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. One exception is the aspect ratio, where Frames allow both 1.91:1 and 1:1 images.

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({ title: 'Frog Frame' })
 
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({ title: 'Frog Frame' })
 
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 },
  title: 'Frog Frame',
})
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.

Fonts

Below is an example of using fonts property in imageOptions.

Google fonts
import { Frog } from 'frog' 
 
export const app = new Frog({
  imageOptions: {
    /* Other default options */
    fonts: [
      {
        name: 'Open Sans',
        weight: 400,
        source: 'google',
      },
      {
        name: 'Open Sans',
        weight: 700,
        source: 'google',
      },
      {
        name: 'Madimi One',
        source: 'google',
      },
    ],
  },
  title: 'Frog Frame',
})
 
app.frame('/', (c) => {
  return c.res({
    image: (
      <div style={{ display: 'flex', flexDirection: 'column' }}>
        <div
          style={{
            color: 'white',
            fontFamily: 'Open Sans',
            display: 'flex',
            fontWeight: 400,
            fontSize: 60,
          }}
        >
          Open Sans (normal)
        </div>
        <div
          style={{
            color: 'white',
            fontFamily: 'Open Sans',
            display: 'flex',
            fontWeight: 700,
            fontSize: 60,
          }}
        >
          Open Sans (bold)
        </div>
        <div
          style={{
            color: 'white',
            fontFamily: 'Madimi One',
            display: 'flex',
            fontSize: 60,
          }}
        >
          Madimi One
        </div>
      </div>
    ),
  })
})

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
import { Button, Frog, TextInput } from 'frog'
 
export const app = new Frog({ title: 'Frog Frame' })
 
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>
    ]
  })
})