celo-personality: The Quiz That Hides a Cross-Chain Identity Stack
A Farcaster Mini App that turns onboarding into a personality test, then verifies identity across Farcaster, Optimism, and Celo behind the scenes.
- The app uses a personality quiz as a disguise for onboarding, not as the product itself.
- Farcaster makes the flow feel native because social identity is already present before the quiz starts.
- The real architecture is an identity sandwich that ties Farcaster auth, Optimism verification, and Celo-flavored interaction together.
- Notifications turn a one-time result into a re-engagement loop, which is where the product becomes useful.
A quiz that is really onboarding
On the surface, celo-personality asks playful questions and returns a Celo-flavored archetype. Under the hood, it is doing something more strategic. It treats the quiz as a cover story for identity resolution, session minting, and future re-engagement.
That matters because most crypto onboarding still starts with the hardest step first. This repo does the opposite. It gives the user something lightweight to do, then uses the result to move them through auth and into the app.
Why this belongs inside Farcaster
Farcaster is not just distribution here. It is the container that makes the whole trick believable. The app can initialize inside the client, call sdk.actions.ready(), and meet users where social identity already exists.
That is a better fit than a standalone landing page because the user is already authenticated as a person, not just a wallet. The mini-app wrapper and quick-auth flow turn social context into the first trusted signal.
The identity sandwich
The technical surprise is that identity is verified in layers. The app receives a Farcaster token, checks it with quick-auth, binds it to the user's FID, and then uses chain data to make sure the same person is still the same person.
The key registry check on Optimism is the part that usually gets missed. Farcaster's trust lives on one chain. The app lives on another. This repo connects them without asking the user to think about the boundary.
// Simplified from apps/web/src/app/api/auth/sign-in/route.ts
import { quickAuthClient } from "@farcaster/quick-auth";
import { SignJWT } from "jose";
export async function POST(req: Request) {
const { token } = await req.json();
const verified = await quickAuthClient.verifyJwt({
token,
domain: process.env.DOMAIN!,
});
const session = await new SignJWT({
fid: verified.fid,
address: verified.custodyAddress,
})
.setProtectedHeader({ alg: "HS256" })
.setIssuedAt()
.setExpirationTime("7d")
.sign(new TextEncoder().encode(process.env.JWT_SECRET));
return Response.json({ session });
}
The important detail is not the JWT syntax. It is the boundary. Farcaster verifies identity, the app issues a local session, and the rest of the mini app can stay light enough to move fast.
The quiz engine keeps the app from feeling like a login form
The quiz itself is state-driven React. It stores the questions as data, maps answers into a small personality model, and calculates the result by counting which archetype appears most often.
That sounds simple because it is supposed to sound simple. The point is to make the value obvious before the machinery shows up. A user gets a result card, a Celo flavor, and a reason to keep going.
Notifications are the hidden second act
The webhook and notification client are what turn a demo into a retention loop. Once the app stores a notification token, it can re-engage users without asking for an email address or phone number.
That is a small implementation choice with a large product effect. The quiz is not the end state. It is a trigger for future messages, future visits, and future identity-aware nudges.
The repo also pays attention to idempotency and ownership checks, which is exactly where toy mini apps usually get sloppy. Here, the aftercare is part of the architecture.
What it replaces
| Typical crypto onboarding | celo-personality |
|---|---|
| Connect wallet first, then try to explain the app. | Answer a quiz first, then let identity and session work happen in the background. |
| Identity is usually reduced to a wallet address. | Identity starts with Farcaster context, then is checked again on-chain. |
| Retention often gets bolted on later. | Notifications are part of the flow from the start. |
| The user feels like they are entering a form. | The user feels like they are entering a social mini app. |
That is why the project matters even as a prototype. It is not trying to make quizzes more entertaining. It is trying to make trust cheaper.