Images & Intents
Farcaster Frames have two main UI components:
- an Image, and
- a set of 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:
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:
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.
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:
import { Button, Frog } from 'frog'
export const app = new Frog({
imageOptions: { height: 600, width: 600 }
})
Property | Type | Default | Description |
---|---|---|---|
width | number | 1200 | The width of the image. |
height | number | 630 | The height of the image. |
emoji | "twemoji" "blobmoji" "noto" "openmoji" | The emoji set to use. | |
debug | boolean | false | Debug mode flag. |
fonts | Font[] | – | The fonts to use. |
headers | HeadersInit | – | Headers for the image response. |
Fonts
Below is an example of using fonts
property in imageOptions
.
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',
},
],
},
})
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:
import { Button, Frog, TextInput } from 'frog'
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>
]
})
})