Skip to content

Guide: State Management in Frames.js

Open in StackBlitz

State in Frames.js is a way for you to store data that you want to use in between frames requests. The frames spec allows up to 4kb of data to be stored in the state object.

Setup

To use state in frames.js, you should declare the initial state in your createFrames call. If your state type is not declared explicitly it will be derived from the initial state.

frames.ts
import { createFrames } from "frames.js/next";
 
export type State = {
  count: number;
};
 
export const frames = createFrames<State>({
  initialState: {
    count: 0,
  },
});

Accessing state

You can access the state object in your frame on the ctx parameter. The initial frame will have the state object with the initial values.

route.tsx
import { frames } from "./frames";
 
const handler = frames(async (ctx) => {
  return {
    image: <div tw="flex">Count: {ctx.state.count}</div>, 
  };
});
 
export const GET = handler;
export const POST = handler;

Updating state

To update the state, you just include the updated state object in your handler's FrameDefinition return value.

route.tsx
import { Button } from 'frames.js/next';
import { frames } from "./frames";
 
const handler = frames(async (ctx) => {
  const currentState = ctx.state;
 
  // Update the state
  const updatedState = { 
    ...currentState, 
    count: ctx.pressedButton ? currentState.count + 1 : currentState.count, 
  }; 
 
  return {
    image: <div tw="flex">Count: {updatedState.count}</div>, ,
    buttons: [
      <Button action="post">Increment</Button>
    ],
    state: updatedState, 
  };
});
 
export const GET = handler;
export const POST = handler;

State protection using a signature

In cases where frame state needs to be trusted, set the stateSigningSecret option in createFrames to sign and verify the state signature on each frame request to guarantee its integrity.

frames.ts
import { createFrames } from "@framesjs/next";
 
export type State = {
  count: number;
};
 
export const frames = createFrames<State>({
  initialState: {
    count: 0,
  },
  stateSigningSecret: "my-secret-key", 
});