Case 3: Raffle events among the filtered casts
guide on how to create the desired frame using frog.fm
** The full code for this example can be found here. ** You can check the operation of the completed sample here. ** This example demonstrates creating a frame via frog.fm. For more details about frog, please refer to the official documentation below.
This example sequentially takes the following three inputs and randomly selects one of the authors from the filtered casts based on those inputs.


Data Query Using Lum0x SDK 1) The
getUserDisplayName
function and thegetUserPfpUrl
function are used to retrieve user information throughLum0x.farcasterUser.getUserByFids
export async function getUserPfpUrl(fid: number): Promise<string> { const res = await Lum0x.farcasterUser.getUserByFids({ fids: String(fid) }); const user = res.users[0]; return user.pfp_url; } export async function getUserDisplayName(fid: number): Promise<string> { const res = await Lum0x.farcasterUser.getUserByFids({ fids: String(fid) }); const user = res.users[0]; return user.display_name; }
2) The part that retrieves the feed is done through
Lum0x.farcasterUser.getFeed
let res = await Lum0x.farcasterFeed.getFeed({ feed_type: "filter", filter_type: "channel_id", channel_id: channel, limit: limit, });
Managing input data for each screen as state 1) Set
initialState
const app = new Frog({ assetsPath: "/", basePath: "/api", hub: neynar({ apiKey: process.env.NEYNAR_API_KEY ?? "" }), title: "Raffle among your fans", imageAspectRatio: "1:1", imageOptions: { height: 800, width: 800, }, initialState: { channel: "", startDate: "", limit: 25, }, });
2) Update state with values entered via TextInput
(using deriveState
, previousState
)
c.deriveState((previousState: any) => {
previousState.channel = c.inputText;
});
Adding an Image to the Screen and Binding Data 1) Add Image
app.frame("/limit", async (c) => {
const fid = c.frameData?.fid;
await postLum0xTestFrameValidation(Number(fid), "limit");
c.deriveState((previousState: any) => {
previousState.endDate = c.inputText;
});
return c.res({
image: "/Steps.png",
intents: [
<TextInput placeholder="Enter limit... default: 25" />,
<Button action="/end-date">Back</Button>,
<Button action="/raffle">Next</Button>,
],
});
});
2) Data Binding
Pass the return value of the getShareImage
function to the image
property of the frame
.
getShareImage
is a function that returns a <BOX/>
element.
app.frame("/result", async (c: any) => {
const { channel, startDate, limit } = c.previousState;
const winner: Participant = await getUser(channel, startDate, limit);
const displayName = await getUserDisplayName(winner.fid);
const pfpUrl = await getUserPfpUrl(winner.fid);
return c.res({
image: getShareImage(displayName, pfpUrl),
intents: [<Button action="/">Home</Button>],
});
});
4. Add postLum0xTestFrameValidation
By adding this part, the user information of those who pressed the frame will be sent to Lum0x, and later, statistics based on this data will be provided.

Please deploy the completed project code on Vercel. For instructions on how to deploy via Vercel, refer to this guide here.
Last updated