
X.com POAP Dispenser
Twitter bot validates coded image tweets and lets users log in to claim unique POAP mint links now!
Demo
About
Community moments deserve more than a post—they deserve to be kept, remembered, and collected. Our project transforms social‑shared experiences into on‑chain souvenirs by turning posts into verifiable proof of presence. Whether it’s a concert, a community meetup, or a spontaneous street moment, participants don’t just share their memories online—they mint them into POAPs tied to their identity. The result is a bridge between lived experiences, social expression, and collectible digital artefacts. Instead of claiming a POAP passively, we anchor each claim to user‑generated content. The memory itself becomes the ticket. User scans QR >> User logs in with Twitter >> System assigns a unique claim code to that Twitter user >> User posts a tweet including code + image >> Bot monitors tweets for valid posts >> Backend verifies tweet authenticity + code ownership + media >> User is authorized to mint a unique POAP linked to their account Why it matters : Links real participation to real content converting social proof into on‑chain proof. Rewards storytelling instead of passive claiming Turns memories into permanent digital artifacts By making experiences collectible, we give communities a new way to share, authenticate, and remember the moments that matter.
How it's made
We built **xbot** as a full-stack TypeScript app where a single codebase orchestrates the Twitter bot, the admin console, and the claim experience. The frontend is **Next.js 16 App Router + React 19 + Tailwind CSS**, backed by **PostgreSQL via Prisma**. Authentication is handled with **NextAuth.js using Twitter OAuth 2.0**, so the same Twitter identity is used both to log into the claim UI and to link back to the tweets the bot processed. On the backend, we keep things very explicit and boring-on-purpose. A set of API routes under `/api/admin` exposes configuration, stats, and CSV exports; `/api/deliveries` serves the authenticated user’s POAP deliveries; and `/api/cron/process-tweets` is the brain of the bot. That cron endpoint is hit by **Vercel’s scheduled functions**, protected by a `CRON_SECRET` check so it can’t be called publicly. On each run, the bot loads the current config from Postgres (hashtag, required code, POAP event, reply template), calls **Twitter API v2** to pull eligible tweets, and then talks to the **POAP API** to reserve unique mint links before persisting a “delivery” record via Prisma. This cleanly decouples “found a tweet” from “user actually clicked and claimed”. The web claim flow and admin UI are just thin React layers on top of those APIs. The claim page uses NextAuth session data to fetch deliveries for the logged-in Twitter account and renders a simple state machine: no deliveries / pending / ready-to-claim. The admin dashboard lives under `/admin` and is built as small Tailwind-styled components on top of `/api/admin/config`, `/api/admin/stats`, and `/api/admin/deliveries` so organizers can tune the bot and export results without touching code. Tests are wired with **Jest** and **Playwright** so we can exercise both the bot logic and the main flows end-to-end, and everything is deployed on **Vercel** with a single `vercel.json` wiring the cron job.