Tappalo — NFC review cards for venues
An NFC card or QR sends customers to the Google review box, and every step is tracked.
- Next.js
- React
- TypeScript
- Prisma
- PostgreSQL
- Neon
- Google Places API
- Tailwind
- 9 / 36commits are mine; the other 27 are my teammate's
- +3,200lines added in my commits, 926 removed
A tap, a review, a level up
Tap a block to see what it does.
- Logic
- Data
- Output
- People
- Input
The heart of the system
NFC review loop
A tap opens the Google review box. The daily sync then sees each new real review and turns it into XP, badges and a score the owner watches climb.
Connected to Daily review sync, Branded page
Logic
Branded page
Per-venue page that opens the Google review box, or a direct redirect. Each step (tap, Google click, social click) is posted to a tracking API. Teammate's part.
- Next.js
Gets from Card tapHands to Production DB (mine), NFC review loop
Logic
Daily review sync
A daily cron pulls rating and reviews from Google Places, saves a snapshot and keeps only reviews not seen before. Teammate's part.
- Google Places API
- Cron
Gets from NFC review loopHands to Growth engine (mine), Production DB (mine)
Logic
Growth engine (mine)
XP for each new review and 5-star, one-off milestones from 10 to 10,000 reviews, daily caps per action, streaks, 10 levels, 15 badges, 0 to 100 score.
- TypeScript
Gets from Daily review syncHands to Production DB (mine)
Data
Production DB (mine)
PostgreSQL on Neon through Prisma, with SQLite kept for local development. I added the models for growth actions, goals, badges and the Brand Vault.
- PostgreSQL
- Neon
- Prisma
Gets from Branded page, Daily review sync, Growth engine (mine), Card requests (mine)Hands to Owner dashboard
Output
Owner dashboard
KPIs, reviews, reply drafts, competitors and plan locks (teammate's), plus the growth path and Brand Vault (mine), with animated progress.
- React
- Tailwind
- framer-motion
Gets from Production DB (mine)
People
Card requests (mine)
The request form now saves each order to the database, and an admin page lists and updates them instead of losing them in a message.
- Next.js
- Prisma
Hands to Production DB (mine)
Input
Card tap
A customer taps the NFC card on the counter or scans its QR code. Cards and QR codes are generated per venue. Teammate's part.
- NFC
- QR
Hands to Branded page
The problem
Restaurants, bars and barbers get few Google reviews even when customers are happy: there is no simple gesture at the right moment and no way to measure the result. The product answers with an NFC card or a QR code that opens a branded page and then the review box.
What I built
- I moved production from SQLite to PostgreSQL on Neon through Prisma, keeping SQLite for local work.
- I built the growth path: a 0 to 100 reputation score, XP, 10 levels, daily streaks and 15 badges, with missions drawn from the venue's real numbers.
- I tied XP to the existing daily Google sync, so points come only from new real reviews and from review-count milestones.
- I added the Brand Vault, saved card requests to the database with an admin panel to handle them, and revised what each plan unlocks.
- I removed a hard-coded admin password from the repo.
The hard part
Making the game impossible to fake. XP comes only from the daily Google sync: a review earns points the first time the sync sees it, each milestone pays once and actions have daily caps, so progress follows real reviews instead of clicks.
Result
The product is live under a new name on its own domain. My 9 of 36 commits added about 3,200 lines: the production database, the growth path with Brand Vault, card requests with their admin panel and the password fix.
My role
In a team of two: my teammate built the Next.js base and most of the product (27 of 36 commits); my parts are the ones above, written with Claude Code.