Skip to main content

Chat Frames with XMTP

The XMTP community has been actively discussing and implementing ways to enhance user experience by supporting frames within XMTP applications. An effort in this direction is detailed in a community post Supporting Frames in XMTP.

Open Frames

XMTP contributes to the Open Frames standard, fostering interoperability and open standards.

Third Party Tools

These tools already provide integration support interoperable Frames.


Third party frameworks and tooling who have already integrated XMTP signing into their offerings:

  • OnChainKit: Discover how OnchainKit seamlessly incorporates XMTP payloads.
  • Frames.js: Learn about the integration of XMTP payloads within FrameJS.


Some clients are fully XMTP compatible and can render Frames signing XMTP payloads:

  • Engage with Frames firsthand by trying them on web.
  • Converse: Converse is Frame compatible. Send your Frames through Converse.

Getting started

These are the foundational tools that allow developers to create, sign, and manage Frames. The protocol libraries are essential for interacting with the XMTP network at a lower level, handling the creation of frames, signing payloads, and managing frame actions. Key aspects include:

  • Declare Protocol Compatibility: Ensure your application can interact with Frames by declaring protocol compatibility.
  • Manage requests: Checks if a URL in message content is suitable for frame processing.
  • Validate incoming messages: Implements security measures to authenticate and secure frame actions, ensuring the integrity and origin of frame interactions.

Protocol compatibility

In compliance with Open Frames, Use a meta tag in your frame's HTML to declare the client protocols your frame supports.

<meta property="of:accepts:xmtp" content="vNext" />

This informs client applications about the protocols your frame can interact with.

Manage requests

These packages enable your frame to send, receive requests across different protocols.

yarn install @xmtp/frames-client
const xmtpClient = await Client.create(wallet);
const framesClient = new FramesClient(xmtpClient);

const frameUrl = "";

// Read data from a frame
const frameMetadata = await framesClient.proxy.readMetadata(frameUrl);

// Get a proxied image URL, which you can use directly in an <image> tag
const imageUrl = framesClient.proxy.mediaUrl(

// Handle a click to button 2 from a conversation with topic "/xmtp/0/123" and participant addresses "abc" and "xyz"
const payload = await signFrameAction({
buttonIndex: 2,
conversationTopic: "/xmtp/0/123",
participantAccountAddresses: ["abc", "xyz"],

// If the button action type was `post`
const updatedFrameMetadata = await, payload);
// If the button action type was `post_redirect`
const { redirectedTo } = await framesClient.proxy.postRedirect(

Validate incoming messages

To start, add the necessary XMTP packages to your project:

yarn install @xmtp/frames-validator

Implement message validation using @xmtp/frames-validator to ensure the authenticity of incoming POST requests. This step is crucial for security, especially when dealing with multiple protocols.

import { validateFramesPost } from "@xmtp/frames-validator";

export function handler(requestBody: any) {
if (requestBody.clientProtocol.startsWith("xmtp")) {
const { verifiedWalletAddress } = await validateFramesPost(requestBody);
// Handle verified XMTP payload
} else {
// Handle Farcaster or other protocol payloads

Was the information on this page helpful?
powered by XMTP