✨ Try it live:
https://friend-verify.vercel.app
A Farcaster Mini App that enables secure, cryptographically-verified friendship confirmations between users. Built with Next.js, Neynar API, and Upstash Redis.
- Cryptographic Signature Verification: All frame interactions are validated using Farcaster's native signature mechanism via Neynar API
- Identity Authentication: Real FID (Farcaster ID) extraction and username validation
- Authorization Controls: Only intended users can verify their friendship
- Collision-Safe Storage: Redis keys use sorted FIDs to prevent duplicate records
- Rate Limiting: Built-in protection against abuse with 5 requests per 10 seconds per IP
- Error Handling: Robust protection against invalid payloads, forgery attempts, and edge cases
- Why Next.js: Better integration with Vercel, built-in API routes, superior TypeScript support, and seamless deployment
- App Router: Modern React patterns with server components and improved performance
- API Routes: Serverless functions with automatic scaling
├── app/
│ ├── api/frame/route.ts # Main Frame API endpoint
│ ├── layout.tsx # Root layout with metadata
│ ├── page.tsx # Main page component
│ └── globals.css # Global styles
├── components/
│ ├── FrameWrapper.tsx # Frame preview component
│ └── Generator.tsx # URL generation interface
├── lib/
│ ├── types.ts # TypeScript definitions
│ ├── neynar.ts # Neynar API client
│ ├── redis.ts # Upstash Redis client
│ ├── username-resolver.ts # Username to FID resolution
│ └── errors.ts # Error handling utilities
└── Configuration files...
- Node.js 18+
- Neynar API account (free tier available)
- Upstash Redis database (free tier available)
git clone https://github.com/logiccrafterdz/friend-verify-frame.git
cd friend-verify-frame
npm installCopy the example environment file:
cp .env.example .env.localNeynar API Key:
- Visit neynar.com
- Sign up for a free account
- Navigate to API Keys section
- Generate a new API key
Upstash Redis:
- Visit upstash.com
- Create a free account
- Create a new Redis database
- Copy the REST URL and Token from database details
Edit .env.local with your actual values:
NEYNAR_API_KEY=your_actual_neynar_api_key
UPSTASH_REDIS_REST_URL=https://your-actual-redis.upstash.io
UPSTASH_REDIS_REST_TOKEN=your_actual_redis_token.env.local to Git. It contains sensitive credentials.
npm run devVisit http://localhost:3000 to see the application.
npm run build- GitHub repository with your code
- Vercel account (free tier available)
- Environment variables ready (from setup above)
-
Connect Repository
- Push your code to GitHub
- Visit vercel.com and sign in
- Click "New Project" and import your repository
-
Configure Environment Variables
- In Vercel dashboard, go to Project Settings → Environment Variables
- Add the following variables:
NEYNAR_API_KEY=your_actual_neynar_api_key UPSTASH_REDIS_REST_URL=https://your-actual-redis.upstash.io UPSTASH_REDIS_REST_TOKEN=your_actual_redis_token
-
Deploy
- Click "Deploy" - Vercel will automatically build and deploy
- Your app will be available at
https://your-project.vercel.app
-
Automatic Deployments
- Future pushes to main branch will auto-deploy
- Preview deployments created for pull requests
Objective: Verify successful friendship confirmation between two real Farcaster accounts
Steps:
- Generate frame URL with both usernames
- Share frame URL in Farcaster (Warpcast recommended)
- Have one user click "Yes, we're friends!" button
- Verify success message appears
- Attempt to click again - should show "Already Verified"
Expected Results:
- ✅ First click: "Friendship Verified!" message
- ℹ️ Second click: "Already Verified!" message
- 🔒 Friendship record stored in Redis
Objective: Ensure unauthorized users cannot verify friendships
Steps:
- Generate frame URL for userA and userB
- Have userC (different account) attempt to click the button
- Verify rejection message
Expected Results:
- ❌ "Unauthorized - Only userA or userB can verify this friendship"
- 🚫 No friendship record created
Objective: Test behavior with non-existent Farcaster usernames
Steps:
- Generate frame URL with invalid username
- Attempt to interact with frame
Expected Results:
- ❌ "User(s) not found: nonexistentuser123"
- 🔍 Username resolution fails gracefully
Objective: Verify API robustness against invalid payloads
Steps:
- Send POST request to
/api/framewith invalid JSON - Send request with missing required fields
- Send request with invalid content-type
Expected Results:
- ❌ Appropriate error frames for each scenario
- 🛡️ No server crashes or security vulnerabilities
- 📊 Proper HTTP status codes (400, 401, 405, 500)
Handles Farcaster Frame Action payloads for friendship verification.
Request Body: Farcaster Frame Action Payload
{
untrustedData: {
fid: number,
url: string,
messageHash: string,
timestamp: number,
network: number,
buttonIndex: number
},
trustedData: {
messageBytes: string
}
}Response: Frame Response
{
image: string, // URL to frame image
buttons: string[] // Array of button labels (empty for final states)
}Error Handling:
400: Invalid request format or missing parameters401: Invalid cryptographic signature403: Unauthorized user attempting verification405: Invalid HTTP method429: Rate limit exceeded500: Internal server error
- Never trust client data: All user identity claims are verified via Neynar's signature validation
- Farcaster-native signatures: Uses Frame Action signatures, not wallet signatures
- Real-time validation: Every interaction is cryptographically verified before processing
- Minimal data collection: Only stores FIDs, usernames, and timestamps
- No PII storage: No personal information beyond public Farcaster data
- Collision-safe keys: Consistent friendship keys prevent duplicate records
- No information leakage: Error messages don't expose internal system details
- Graceful degradation: Invalid requests return user-friendly error frames
- Rate limiting: Protection against abuse and spam
- English-only interface: Aligned with Farcaster ecosystem standards
- No geographic restrictions: Works globally where Farcaster is accessible
- Timezone-agnostic: All timestamps stored in ISO 8601 UTC format
- Unicode support: Handles international usernames correctly
- Environment variables configured
- Neynar API key valid and active
- Upstash Redis database accessible
- All test cases passing
- Error handling implemented
- Security measures active
- Documentation complete
- Deployment successful
- API response times
- Neynar API rate limits
- Redis connection health
- Error rates by type
- Successful verification count
- Monitor Neynar API usage (free tier limits)
- Check Upstash Redis storage usage
- Review error logs for patterns
- Update dependencies for security patches
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Please ensure all contributions maintain the security-first approach and error handling standards.
This project is licensed under the MIT License - see the LICENSE file for details.
- Farcaster for the decentralized social protocol
- Neynar for the robust API infrastructure
- Upstash for serverless Redis hosting
- Vercel for seamless deployment platform
Developer: LogicCrafterDZ
Email: logiccrafterdz@gmail.com
Twitter: @Arana_lib
Telegram: https://t.me/LogicCrafterDZ