Farcaster Integration
Farcaster—decentralized social protocol with on-chain identity (Ethereum) and off-chain messages (Hubs). Unlike Lens, Farcaster prioritizes speed and developer experience: no gas for every action, no blockchain latency for messages. Rapidly growing ecosystem with Warpcast as primary client.
Farcaster Architecture
FID (Farcaster ID): on-chain identifier on Ethereum (Optimism). Register once, costs gas.
Signers: Ed25519 keys registered for FID. Messages signed with signer key, not Ethereum key. This allows applications to sign messages without access to wallet private key.
Hubs: federated servers storing and syncing Farcaster messages. Neynar, Warpcast, Pinata—examples of Hub providers.
Frames: interactive elements directly in feed—mini-applications inside posts.
Frames—Key Feature for Developers
Frames—OpenGraph-like standard for interactive posts. User sees post with buttons, clicks—server handles action and returns new frame. Can build: mint NFT right from feed, voting, games, onboarding flows.
import { Frog } from "frog";
import { Button, FrameContext } from "frog";
const app = new Frog({ basePath: "/api" });
// Simple frame with NFT minting
app.frame("/mint-nft", async (c: FrameContext) => {
const { buttonValue, frameData } = c;
let status = "ready";
let txHash = "";
if (buttonValue === "mint") {
// Initiate mint transaction
try {
txHash = await mintNFT(frameData?.fid?.toString() ?? "");
status = "minted";
} catch {
status = "error";
}
}
return c.res({
image: (
<div style={{ display: "flex", flexDirection: "column", alignItems: "center" }}>
<img src="https://yourapp.com/nft-preview.png" width="400" height="300" />
{status === "minted" && <p>Minted! TX: {txHash.slice(0, 10)}...</p>}
{status === "error" && <p>Error minting. Try again.</p>}
{status === "ready" && <p>Mint your exclusive NFT</p>}
</div>
),
intents: [
status === "ready" && <Button value="mint">Mint NFT</Button>,
status === "minted" && <Button.Link href={`https://etherscan.io/tx/${txHash}`}>View TX</Button.Link>,
],
});
});
Neynar API—Simplified Integration
Neynar—managed Farcaster API, removes need to run own Hub:
import { NeynarAPIClient } from "@neynar/nodejs-sdk";
const neynar = new NeynarAPIClient({ apiKey: process.env.NEYNAR_API_KEY! });
// Publish cast (post)
const cast = await neynar.publishCast(
signerUUID, // UUID of signer registered via Neynar
"Hello Farcaster! #web3",
{
embeds: [{ url: "https://yourapp.com/post/123" }],
channelId: "dev", // publish to /dev channel
}
);
// Get feed by FID
const feed = await neynar.fetchFeed("following", {
fid: 12345,
limit: 25,
cursor: nextCursor,
});
// Get followers
const followers = await neynar.fetchUserFollowers({ fid: 12345 });
// Search users
const users = await neynar.searchUser("alice", { viewerFid: myFid });
Sign In With Farcaster (SIWF)
Authentication via Farcaster account—analog of SIWE for Farcaster:
import { createAppClient, viemConnector } from "@farcaster/auth-client";
const appClient = createAppClient({
ethereum: viemConnector(),
});
// Create channel for auth
const { channelToken, url, nonce } = await appClient.createChannel({
siweUri: "https://yourapp.com/login",
domain: "yourapp.com",
});
// User scans QR or visits link in Warpcast
// After confirmation—get status
const status = await appClient.watchStatus({ channelToken });
if (status.data.state === "completed") {
const { fid, displayName, pfpUrl, username } = status.data;
// User authenticated
await createUserSession(fid, username);
}
React Hooks for Farcaster
import { AuthKitProvider, useSignIn } from "@farcaster/auth-kit";
function LoginButton() {
const { signIn, isLoading, isSuccess, profile } = useSignIn({
onSuccess: (res) => {
console.log(`Logged in as ${res.username} (FID: ${res.fid})`);
},
});
return (
<button onClick={signIn} disabled={isLoading}>
{isLoading ? "Connecting..." : "Sign In with Farcaster"}
</button>
);
}
function App() {
return (
<AuthKitProvider
config={{
rpcUrl: "https://mainnet.optimism.io",
domain: "yourapp.com",
siweUri: "https://yourapp.com/login",
}}
>
<LoginButton />
</AuthKitProvider>
);
}
Channels and Community Building
Farcaster Channels—thematic feeds (analog of subreddits). Publishing in channel = reach target audience:
// Publish to /gaming channel
await neynar.publishCast(
signerUUID,
"Just deployed our new blockchain game! Check it out 🎮",
{
channelId: "gaming",
embeds: [{ url: "https://game.com" }],
}
);
// Get channel feed
const channelFeed = await neynar.fetchFeedByChannelIds(["gaming", "web3"], {
limit: 25,
withRecasts: false,
});
Farcaster integration—1-2 weeks for Sign In + basic social features. Frames—separately, 1-2 weeks for interactive frame with transactions. Farcaster more developer-friendly than Lens for quick start—rich documentation, Neynar API reduces complexity.







