FIP: Frames v2 #205
Replies: 15 comments 26 replies
-
Is 1.91:1 being confirmed as the official ratio for the initial frame image? Or is this just being marked as an example? Overall super excited for these changes, lots to unpack here! |
Beta Was this translation helpful? Give feedback.
-
I would like to be able to opt out of notifications separately, without unfavoriting. The name change suggests this is replacing the old the frames entirely and warpcast will stop supporting them, correct? |
Beta Was this translation helpful? Give feedback.
-
Can we get more details on the Not particularly sure what |
Beta Was this translation helpful? Give feedback.
-
Some open questions or thoughts I have:
Agree this would be nice. Perhaps a hub can sign certain data or the signed TLS packaged can be passed on from the hub to the miniapp here, so the Mini-app doesn't need to trust the client, but still get the preloaded hub data?
I think this might be helpful especially with the way frames v1 went where many of the changes were not backwards compatible with clients. Many clients had incomplete or outdated implementations. Passing along the context may help solve this, as Frames would be able to feature detect clients compatibility rather than breaking, although perhaps a frames version passed into the context is a better solution.
Passing along the I think this is very exciting direction for Frames, but I think suggestion (1) above is essential for allowing open developer legos to emerge in v2 like it did in v1 |
Beta Was this translation helpful? Give feedback.
-
V1 frames are like enhanced OpenGraph tags with a bit of interactivity, perfect for sharing content. Developers have pushed them to do more complex things, which isn’t their intended purpose. This has made V1 frames underused, but the real issue is a lack of support and tools. Problems: No plugins for major CMS platforms. tl;dr: V1 frames are great for simple, interactive content sharing. They’re just underutilized, not bad. Don’t throw them out—they deserve better tools and promotion. |
Beta Was this translation helpful? Give feedback.
-
Looks cool, especially for static apps!
|
Beta Was this translation helpful? Give feedback.
-
This looks good because, de facto, frames v2 will inherit in fact what was mini-apps, and make them permissionless. This is something that was mentioned and requested many many times on Farcaster. IMO Iframes proved already that are superior, as I said, even before v1 was in spec design. It is still overall a client-only feature, and Farcaster being a protocol it seems confusing that this is categorized as an FIP. As is just a client spec, not an FIP, might be a technicality but I think is important, to not overmarket it. |
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
I'm struggling to understand the difference between this and mini apps that already exist. Feel like there is a lot of overlap and will shut out amateur coders who were able to learn the simplicity of coding a frame, but can't code a full web app. Also, think there is something to be said for keeping the user interaction in-feed, having stuff pop up over the full screen is less user friendly (why mini apps have struggled to take off so far) |
Beta Was this translation helpful? Give feedback.
-
should be context.user.pfpUrl instead of context.user.pfp right? |
Beta Was this translation helpful? Give feedback.
-
Should it be |
Beta Was this translation helpful? Give feedback.
-
I find the Farcaster object in this documentation very confusing. When the documentation instructs you to call:
you include it in your code, only to discover that it doesn’t work. It should be made very clear that this object is not part of the final implementation and that you need to use a library to access it. Additionally, why isn’t it a real object? Why do we need to rely on another library to use it? |
Beta Was this translation helpful? Give feedback.
-
Assuming that > await sdk.actions.requestAuthToken({challenge: "unique-one-time-cryptographic-challenge-abc-123"});
"0xabcd...1234" This follows the same principals as webauthn where presence of a challenge is meant to prevent replay attacks. type RequestAuthToken = (
options: Partial<{
/**
* When this token should be considered invalid.
* @default 15 minutes from now
*/
exp?: number;
/**
* A cryptographic challenge produced by the relying party
* to prevent replay attacks.
*/
challenge?: string;
}>
) => Promise<string>; @varunsrin is this a reasonable addition or are there other factors that may make this difficult? |
Beta Was this translation helpful? Give feedback.
-
Re: Notifications. Users will be able to mute at the app level. But does the frame know that it has been muted? I think this would be an important piece of info that Frames could use. Some ideas:
|
Beta Was this translation helpful? Give feedback.
-
following up on what other have already stated:
imo, v1 satisfies different use-cases than what is planned for v2 (which seems more like a web app than a "simple" frame) my first frame project is almost complete, and I've committed to make use of both v1 and v2; to benefit from their respective strengths, while avoiding their weaknesses. tl;dr -- calling a (pre-authenticated) v2 app from a v1 (in-feed) frame would seem to me like the best of both worlds |
Beta Was this translation helpful? Give feedback.
-
Problem
Developers want users to discover and use their onchain apps. Farcaster was great for discovery but not so much for usage. If you found an app in your feed, you had to click the link, load a page and connect it to a wallet. It was navigable on desktop, but nearly impossible on mobile even for advanced users.
Frames launched in Jan 2024 and make this a bit better. When a user clicked on a frame, the developer knew the identity of the user and their wallet address. They could send things to the users wallet and the user could take actions through a limited set of interactions. This was neat and we saw a lot of apps built, but there were some limitations that caused their usage to peter out:
A new frame standard that allows interactive applications, onchain transactions and user notifications would enable many new kinds of social applications.
Specification
A frame is full-screen application that renders inside a Farcaster app.
It can be embedded in feeds in a compact form which includes an image and a button which opens the frame. When the button is clicked the frame URL is rendered in an in-app browser. Developers can build anything that renders in a browser and can use a JavaScript SDK to trigger actions like saving the frame or requesting an onchain transaction.
Frames will have access to :
Here's an example of a frame using a wallet to complete a transaction:
Frame URL Specifications
A URL is considered a valid frame if it includes an embed tag in its HTML
<head>
and a manifest file at a well known location at the root of the domain.Versioning
Frames will follow semantic versioning and frames must declare the version that they support. Apps will choose to render frames based on the versions they can support.
Frame Embed Metatags
A frame URL must have a FrameEmbed in a serialized form in the
fc:frame
meta tag in the HTML<head>
. When this URL is rendered in a cast, the image is displayed in a 3:2 ratio with a button underneath. Clicking the button will open an app frame to the provided action url and use the splash page to animate the transition.Frame Manifest
The manifest file declares the metadata that is applied to the frame application served from this domain. It also defines triggers that indicate which actions it supports from trigger points like casts and the composer.
Frame servers must provide a JSON manifest file on their domain at the well known URI
/.well-known/farcaster.json
.Domain Account Association
The account association links the domain to a Farcaster account. The signature must be a signed JSON Farcaster Signature from the account's custody address with the following payload:
The domain in the signed object must match the domain the manifest is served from.
Frame Config
Frame Invocation
Frames may be invoked in the following ways. When invoked, the frame application may receive additional information about the context in which it was launched.
homeUrl
defined in the frame application manifest.url
specified in the FrameEmbed metadata.targetUrl
specified in the notification payload.Triggers
Triggers allow a user to launch into your frame application from different places in a Farcaster client application. These will eventually replace "cast actions" and "composer actions." See Feature: Triggers in the Appendix for further details.
The frame receives the trigger type and id as context data.
Frame manifest caching
Farcaster clients may cache the frame manifest when scraping embeds, but should provide a mechanism for refreshing the manifest file.
Frame UI Specifications
Header
Clients should render a header above the frame that includes the name and author specified in the manifest. Clients should show the header whenever the app frame is launched.
Splash Screen
Clients should show a splash screen as soon as the app is launched. The icon and background must be specified in the frame manifest or embed meta tags. The frame can hide the splash screen once loading is complete.
Size & Orientation
A frame should be rendered in a vertical modal. Mobile frame sizes will be dictated by device dimensions while web frame sizes will be set to 424x695px.
Client SDK API
Frame applications must include a frame SDK JavaScript package to communicate with the parent app. Frames may include it as a bundled package or using a
<script>
tag.The frame SDK manages frame-client communication over a
window.postMessage
channel. Since the parent app cannot inject arbitrary JavaScript in a browser context, frame applications must include the SDK in their app to establish a communication channel.The
sdk.context
variable provides information about the context within which the frame is running:context.location
Contains information about the context from which the frame was launched.
Cast Embed
Indicates that the frame was launched from a cast (where it is an embed).
Notification
Indicates that the frame was launched from a notification triggered by the frame.
Launcher
Indicates that the frame was launched directly by the client app outside of a context, e.g. via some type of catalog or a notification triggered by the client.
context.user
Details about the calling user which can be used to customize the interface. This should be considered untrusted since it is passed in by the application, and there is no guarantee that it was authorized by the user.
context.client
Details about the Farcaster client running the frame. This should be considered untrusted
clientFid
: the self-reported FID of the client (e.g. 9152 for Warpcast)added
: whether the user has added the frame to the clientsafeAreaInsets
: insets to avoid areas covered by navigation elements that obscure the viewnotificationDetails
: in case the user has enabled notifications, includes theurl
andtoken
for sending notificationsUsing safeAreaInsets
Mobile devices render navigation elements that obscure the view of a frame. Use
the
safeAreaInsets
to render content in the safe area that won't be obstructed.A basic usage would to wrap your view in a container that adds margin:
However, you may want to set these insets on specific elements: for example if
you have tab bar at the bottom of your frame with a different background, you'd
want to set the bottom inset as padding there so it looks attached to the
bottom of the view.
actions.ready
Indicates that the application is fully loaded and ready to displayed to users. Once this is called the loading screen will be hidden. Frame applications MUST call
ready()
to display their app.actions.openUrl
Request the client app to direct the user to an external URL via deep link or web browser.
actions.close
Close the app frame and display an optional toast.
wallet.ethProvider
An EIP-1193 Ethereum Provider for interacting with the user’s connected wallet. App Frames can interact with this provider using familiar tools like wagmi to:
eth_requestAccounts
)eth_sendTransaction
)eth_signTypedData_v4
)Rationale
FAQ
What about older frame types / cast actions / composer actions / mini-apps?
Older frame types will be fully supported for now until we develop a thorough transition plan. We will give developers at least 3 months notice before deprecating anything.
Release Plan
Schedule
Changelog
Appendix
Feature: Auth
Allow users to sign into frames using their Farcaster identity.
actions.signIn
Initiates a Sign In with Farcaster flow for the user. The Frame host must set
the
domain
value of the SIWF message to the domain of the frame and theuri
value of the url of the Frame. When validating this message the
domain
mustbe checked.
Feature: Add frame
The user can add a frame to their Farcaster app, either through an SDK action or directly (from a deep link, catalog page, etc). The Farcaster app should make it easy to find this saved frame in their UI and accept notifications from the app developer and deliver them to the user. For example, a frame which monitors onchain prices could notify users when the price of something exceeds a certain threshold.
Request add frame
Asks the user to add the frame to the Farcaster app, which allows the user to invoke the frame from a cast, composer or other locations in the app. Also allows the app to send notifications to the user.
actions.addFrame
Request the user to add the frame, which adds it to the user's favorites list and allows the frame server to send in-app notifications to the user. The Farcaster client is expected to prompt the user for confirmation. Per session, only a single prompt should be shown (repeated calls to
addFrame()
should immediately result in a.rejected_by_user
error). When the client supports notifications, returns anotificationDetails
object with a notification callback URL and token.There are 2 expected failure conditions which the frame should gracefully handle:
invalid_domain_manifest
: The frame domain manifest is invalid. The frame developer should use the developer tools to validate and fix their manifest.rejected_by_user
: Returned when the user rejects/dismisses the prompt asking them to add the frame, or the frame has triggeredaddFrame()
more than once per session.Feature: Server Events
The Farcaster client server POSTs 4 types of events to the frame server at the
webhookUrl
specified in its frame manifest:frame_added
frame_removed
notifications_enabled
notifications_disabled
The body looks like this:
Events use the JSON Farcaster Signature format and are signed with the app key of the user. The final format is:
All 3 values are
base64url
encoded. The payload and header can be decoded to JSON, where the payload is different per event.frame_added
: frame added to a clientThis event may happen when an open frame calls
actions.addFrame
to prompt the user to favorite it, or when the frame is closed and the user adds the frame elsewhere in the client application (e.g. from a catalog).Adding a frame includes enabling notifications.
The Farcaster app server generates a unique
notificationToken
and sends it together with thenotificationUrl
that the frame must call, to both the Farcaster app client and the frame server. Client apps must generate unique tokens for each user.The app client then resolves the
actions.addFrame
promise so the frame can react immediately (without having to check its server).This is the flow for an open frame:
This is the flow when the frame is not open; only the backend part runs:
Webhook payload:
frame_removed
: user removed frame from clientA user can remove a frame, which means that any notification tokens for that fid and client app (based on signer requester) should be considered invalid:
Webhook payload:
notifications_disabled
: user disabled notificationsA user can disable frame notifications from e.g. a settings panel in the client app. Any notification tokens for that fid and client app (based on signer requester) should be considered invalid:
Webhook payload:
notifications_enabled
: user enabled notificationsA user can enable frame notifications (e.g. after disabling them). The client backend again sends a
notificationUrl
and atoken
, with a backend-only flow:Webhook payload:
Feature: Frame Events
Farcaster clients emit events to your frame, while it is open, to let you know of actions the user takes.
To listen to events, you have to use
sdk.on
to register callbacks (see full example).Ensure that on unmount/close, all the listeners are removed via
sdk.removeAllListeners()
.Here are the callback definitions:
The emitted events are:
frameAdded
, same as theframe_added
webhookframeAddRejected
, frontend-only, emitted when the frame has triggered theaddFrame
action and the frame was not added. Reason is the same as in the return value ofaddFrame
.frameRemoved
, same as theframe_removed
webhooknotificationsEnabled
, same as thenotifications_enabled
webhooknotificationsDisabled
, same as thenotifications_disabled
webhookFeature: Notifications API
A frame server can send notifications to one or more users who have enabled them.
The frame server is given an authentication token and a URL which they can use to push a notification to the specific Farcaster app that invoked the frame. This is private and must be done separately for each Farcaster app that a user may use.
The frame server calls the
notificationUrl
with:notificationId
: a string (max size 128) that servers as an idempotency key and will be passed back to the frame via context. A Farcaster client should deliver only one notification per user pernotificationId
, even if called multiple times.title
: title of the notification, max length of 32 charactersbody
: body of the notificationtargetUrl
: the target frame URL to open when a user clicks the notification. It must match the domain for which the notification token was issued.tokens
: an array of tokens (for thatnotificationUrl
) to send the notification to. Client servers may impose a limit here, e.g. max 10000 tokens.Client servers may also impose a rate limit per
token
, e.g. 5 sends per 5 minutes.The response from the client server must be an HTTP 200 OK, with the following 3 arrays:
successTokens
: tokens for which the notification succeededinvalidTokens
: tokens which are no longer valid and should never be used again. This could happen if the user disabled notifications but for some reason the frame server has no record of it.rateLimitedTokens
: tokens for which the rate limit was exceeded. Frame server can try later.Once a user has been notified, when clicking the notification the client app will:
targetUrl
NotificationLaunchContext
Farcaster apps should:
Feature: Triggers
Contexts
A frame can be launched from different contexts like a cast or direct message. In each case, the frame app receives a context object that contains information about how the frame was triggered. The context may also define what SDK functions are available. For example, a "translate" frame launched from the
composer
context will have a method that allows it to update the cast being written, while one triggered from acast
context in the feed will only get the contents of the cast.Contexts unify cast actions, composer actions, frames and mini-apps into a single standard, instead of having custom flows for each of these features.
A single frame may expose multiple cast and composer triggers via the TriggerConfig in its frame application manifest. When invoked, the context will include the ID of the trigger that was activated.
We intend to introduce additional triggers in the future, replacing "cast actions" and "composer actions" and introducing new launch contexts:
Context types
Feature: Primary Button
actions.setPrimaryButton
Action Button
A native action button may be rendered via an SDK call which provides a clear and consistent call to action for the user. The app frame can specify the text, color mode and callback function. This is optional and frames may choose to implement their own user interface using UI components inside the web view.
Set the Primary Button.
An app frame should subscribe to the
primaryButtonClicked
event to respond to interactions.primaryButtonClick (Event)
Emitted when user clicks the Primary Button.
Beta Was this translation helpful? Give feedback.
All reactions