MVP for a Base-chain NFT social identity loop:
- X OAuth login
- Base wallet signature verification
- Backend-only NFT score calculation
- Dashboard and public leaderboard
- Chrome Manifest V3 extension that displays score on
x.comprofiles
npm install
cp .env.example .env.local
npm run devFill .env.local with X OAuth, Supabase, NFT provider, Base RPC, and collection settings. Do not use XAMPP.
Required Supabase setup:
- Create a Supabase project.
- Run supabase/schema.sql in the SQL editor.
- Add
NEXT_PUBLIC_SUPABASE_URLandSUPABASE_SERVICE_ROLE_KEYto.env.local.
Edit lib/config/score-rules.ts to change:
- Target NFT contract
- Early token threshold
- Points for project NFT, additional NFTs, rare traits, and early token IDs
- Rare trait definitions
NFT fetching is behind lib/nft/providers.ts. NFT_PROVIDER=mock is useful for local UI testing. alchemy fetches real Base NFT holdings for a wallet. Set TARGET_NFT_CONTRACT_ADDRESS=all to score every NFT in the wallet, or set it to one contract address to score only that collection. rpc is implemented for enumerable contracts only; simplehash and reservoir can be added behind the same interface.
Scam/spam filtering can be tuned with env vars:
NFT_EXCLUDE_SPAM=trueasks Alchemy to remove NFTs it classifies as spam.NFT_REQUIRE_VERIFIED_CONTRACT=trueonly scores NFT contracts with verified source code on Base through Etherscan API v2 (chainid=8453). This is enabled by default because wallet-wide scoring can otherwise include scam airdrops.BASESCAN_API_KEYis required whenNFT_REQUIRE_VERIFIED_CONTRACT=true; use a BaseScan/Etherscan API v2 key. Without it, contracts are treated as unverified.- When verified-contract filtering is enabled, verified source code takes priority over Alchemy spam flags to avoid false positives on legitimate contracts.
NFT_MIN_FLOOR_PRICE_ETH=0.001only scores collections with an available floor at or above that ETH value.
GET /api/mePOST /api/wallet/connectPOST /api/score/refreshGET /api/profile/:handleGET /api/leaderboard
Load the extension directory in Chrome developer mode.
- Open
chrome://extensions. - Enable Developer mode.
- Load unpacked extension from
extension. - Open extension options and set the backend URL if it is not
http://localhost:3000.
The extension only calls GET /api/profile/:handle and injects public score data. It does not contain secrets or calculate scores.
- Push the repo to GitHub.
- Import into Vercel.
- Set the same env vars in Vercel.
- Set
NEXTAUTH_URLandPUBLIC_APP_URLto the deployed URL. - Configure X OAuth callback for
/api/auth/callback/twitter.
Vercel Cron calls GET /api/cron/refresh-scores once per day using vercel.json. The schedule is 0 18 * * *, which runs at 01:00 WIB because Vercel cron schedules use UTC.
Set these env vars in Vercel:
CRON_SECRET: long random secret used to authorize the cron endpoint.CRON_REFRESH_LIMIT=50: maximum latest verified wallets refreshed per cron run.