Farcaster Frames with Model API

Video Tutorial

Welcome to this tutorial where we will walk you through the process of creating a Farcaster Frame and communicating with a FLock.io RAG API. This is a comprehensive guide that will give you the confidence to create, modify, and enhance your Farcaster Frames with FLock API.

What you will learn:

  • How to create a Farcaster Frame

  • Communicate with FLock RAG API.

Technology Stack

  • TypeScript

  • Frog framework

What is Frame?

A Frame is a tool for creating interactive, authenticated apps on Farcaster, allowing features like polls, live feeds, or galleries within Warpcast and other FC clients. Frames enhance the OpenGraph standard, transforming static embeds into interactive experiences.

What is Frog framework?

Frog is a framework built on top of Hono for building Farcaster Frames.

The documentation: Getting started

How it Works


  • Install Frog Framework

npm install frog hono

yarn add frog hono
  • Create a Bot from the AI Co-Creation platform, where you can follow the guide.

  • Install the API related package.

# init frog framework
npm init frog

# install relavent packages
npm install axios dotenv @types/node
  • We will be using the default template, feel free to export other ones in the future.

File structure

 ┣ πŸ“‚public
 ┃ β”— πŸ“œicon.png
 ┣ πŸ“‚src
 ┃ ┣ πŸ“‚api
 ┃ ┃ β”— πŸ“œflock-api.ts
 ┃ β”— πŸ“œindex.tsx
 ┣ πŸ“œ.env
 ┣ πŸ“œ.gitignore
 ┣ πŸ“œREADME.md
 ┣ πŸ“œpackage-lock.json
 ┣ πŸ“œpackage.json
 β”— πŸ“œtsconfig.json
  • Pages will stay in our router

  • FLock API will stay in the utils

Logic flow

We will have one page

  • Default page - react on user’s input

This is a very simple and general approach of how we can use frame with FLock Chat Bot.


Now create a folder under src called api within the utils folder create a file called flock-api.ts this is the place where your api will sit. And here is the code you can use directly.

import axios from "axios";
import * as dotenv from "dotenv";

// Load environment variables from .env file
dotenv.config(); // Make sure the path is correct

async function chatFLockBot(prompt: string, modelId: string) {
  console.log("Prompt:", prompt);

  try {
    // Construct the request payload
    const payload = {
      question: prompt,
      chat_history: [],
      knowledge_source_id: modelId, // replace with your model id

    // Set the headers
    const headers = {
      "x-api-key": process.env.FLOCK_BOT_API_KEY, // Ensure API key is set in .env

    // Send POST request using axios
    const response = await axios.post(

    // Output the response data
    return response.data;
  } catch (error) {
    console.error("Error:", error);

export default chatFLockBot;

Next create a .env file in the root directory of the project, and add following

FLOCK_BOT_API_KEY= "<your api key>"
FLOCK_BOT_ID="<your bot id>"

Useful tools for OG image

I personally think that the Vercel OG image playground is a convenient tool to quickly check up on your OG image. So, do utilise it!

Vercel OG Image Playground

Page Structure

app.frame('/', (c) => {
  const { buttonValue, inputText, status } = c
  const fruit = inputText || buttonValue
  return c.res({
    image: (
    intents: [

Before diving in, let's first understand the structure of a β€˜frame’. A frame consists of two components: the image and the intents.

  • The image is where your visuals are displayed

  • The intents handle interactions, including text input, button reactions, and the new transaction operations.


image: (
      alignItems: 'center',
      background: 'black',
      backgroundSize: '100% 100%',
      display: 'flex',
      flexDirection: 'column',
      flexWrap: 'nowrap',
      height: '100%',
      justifyContent: 'center',
      textAlign: 'center',
      width: '100%',
        color: 'white',
        fontSize: 24,
        fontStyle: 'normal',
        letterSpacing: '-0.025em',
        lineHeight: 1.4,
        marginTop: 30,
        padding: '0 120px',
        whiteSpace: 'pre-wrap',
      {status === 'response' && `Your question is: ${prompt}`}
        color: 'white',
        fontSize: status === 'response' ? 16 : 60,
        fontStyle: 'normal',
        letterSpacing: '-0.025em',
        lineHeight: 1.4,
        marginTop: 30,
        padding: '0 120px',
        whiteSpace: 'pre-wrap',
      {status === 'response' ? response.answer : "Lets chat about FLock!"}

Here we use status condition to show the content, if status is response, we will show the question and answer. Otherwise, the user will only see β€œLets chat about FLock”


intents: [
      <TextInput placeholder="Enter Prompt about FLock" />,
      <Button value={process.env.FLOCK_BOT_ID}>Lets Chat!</Button>,
      status === 'response' && <Button.Reset>Reset</Button.Reset>,

Here we have created three intents

  • TextInput - for questions to be asked to the bot

  • Button - for the interaction

  • Button - for reset after receiving the response

Main logic flow

import chatFLockBot from './api/flock-api'
app.frame('/', async (c) => {
  const { buttonValue, inputText, status } = c
  const prompt = inputText
  const modelId = buttonValue

  let response;

  if (prompt == undefined || modelId == undefined) {
    response = "Detail not satisfied, please insert prompt";
  } else {
    try {
      response = await chatFLockBot(prompt, modelId);

    } catch (e) {
      response = "There is somthing wrong with the process, please try again"

  return c.res({
    image: (
    intents: [

In this section, we establish the logic to respond to both user input and an API call.

Initially, we extract values from the object c (representing context), which provides the current state or frame:

  • buttonValue - the value assigned to a button,

  • inputText - the text entered by the user,

  • status - the status of the context within its lifecycle.

Next, we initialise two constants, prompt and modelId, using the extracted inputText and buttonValue respectively. This sets up the parameters we need for the subsequent API call.

We then employ an if statement to check whether either prompt or modelId is undefined. This validation is crucial as it ensures that we have the necessary data before proceeding.

Finally, we use a try-catch structure to manage the asynchronous function chatFlockBot. This function is called with prompt and modelId as arguments. The try block executes the function, and should any errors occur during the API call, the catch block captures these exceptions and sets an error message.

Run the test

Now you have completed the setup of the frame. Let’s test it in the local environment.

# run this command in your terminal
npm run dev

# you will see followings
> dev
> frog dev

(!) Could not auto-determine entry point from rollupOptions or html files and there are no explicit optimizeDeps.include patterns. Skipping dependency pre-bundling.

  [running] frog@v0.9.0

  ➜  Local:   http://localhost:5173/
  ➜  Inspect: http://localhost:5173/dev
  ➜  Network: use --host to expose

Go to http://localhost:5137/dev

You will see the following page

  1. The history of access

  2. URL tab - similar to web browser URL tab

  3. Metadata of current frame

  4. Live frame interact

  5. Request/Context/Metadata information

  6. Request/Context/Metadata information

Now you can start typing the questions and chat with the frame!

Deploy your frame

I recommend deploying your project using Vercel. You can easily deploy it by connecting your GitHub account and pushing your project to a repository.

Next, all you need to do is copy your deployed link and post it in any Farcaster Client.

Please tag us when you post the cast! β€œ/flock-io”

Lastly here is the GitHub Repository!


Reach out to us by Website: https://flock.io/ Twitter: https://twitter.com/flock_io Telegram: https://t.me/flock_io_community Discord: https://discord.gg/ay8MnJCg2W Farcaster: https://warpcast.com/~/channel/flock-io

Last updated