Drink. Stamp. Earn. — A self-hosted, multi-tenant loyalty platform for coffee shops.
Staff generate short-lived QR codes at the counter; customers scan them to collect points and redeem free drinks.
(This repository (was once a private one) is shared due to portfolio-sharing reasons. So, all of the active changes made in the past may not be shown in the commits.)
🌐 Live demo: quickstamp.com.tr
- ☕ Multi-tenant — any number of coffee shops on a single deployment, each with its own staff, customers, and point balances
- ⏱️ Short-lived QR codes — staff generate time-limited codes, so points can only be earned at the counter
- 🎁 Verified redemptions — customers redeem points for a free drink; staff confirm the redemption by scanning the customer's QR
- 👥 Three roles — customer, staff, and admin (new shop registrations require admin approval)
- 🔐 Self-contained auth — Auth.js v5 credentials login with JWT sessions, bcrypt password hashing, password-reset flow, and per-IP login rate limiting — no third-party auth provider
- 🌍 Bilingual — Turkish and English UI (Turkish default)
- 📱 Installable PWA — mobile-first design, add-to-home-screen support
- 📊 Staff analytics — stamp and redemption history per shop
- 🐳 One-command deploy — Docker Compose with PostgreSQL, health-checked startup, standalone Next.js output
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
| Layer | Technology |
|---|---|
| Framework | Next.js 16 (App Router) · React 19 · TypeScript |
| Database | PostgreSQL 16 (pg, hand-written SQL, no ORM) |
| Auth | Auth.js v5 (JWT credentials) · bcrypt |
| UI | Tailwind CSS 4 · html5-qrcode |
| Infra | Docker · Docker Compose |
cp .env.sample .env # edit with secure values
docker compose up -d # PostgreSQL + app on http://localhost:3000Default admin account: admin@quickstamp.local / admin123 — change this after first login.
Optional pgAdmin console:
docker compose --profile tools up -d # pgAdmin on :5050cp .env.sample .env # if you haven't already
docker compose up -d db # start PostgreSQL only
npm install
npm run dev # dev server on http://localhost:3000The dev server connects to the database via DATABASE_URL in .env — if you
change any DB_* value, update DATABASE_URL to match.
Testing the camera on a phone? Browsers only expose the camera over HTTPS. Generate local certs (e.g. with mkcert) into
certs/and runnpm run dev:https.
- A shop registers and is approved by the platform admin.
- Staff open the shop dashboard and generate a QR code — each code is valid for a short window.
- The customer scans the code with their phone and a point is added to their balance at that shop.
- When enough points accumulate, the customer taps Redeem — this produces a redemption QR.
- Staff scan the redemption QR to confirm the free drink, closing the loop.
Five tables, multi-tenant by shop_id:
shops— registered coffee shops (with approval status)users— customers, staff, and admins (role-based)qr_codes— short-lived stamp tokens issued by staffpoints— point ledger per customer per shoprewards— redemptions with verification tokens
Schema is initialized automatically from sql/init.sql on first startup.
src/
├── app/
│ ├── api/ # REST endpoints (auth, admin, staff, customer, rewards)
│ ├── admin/ # admin dashboard (shop approvals, user management)
│ ├── staff/ # staff dashboard (QR generation, scanning, analytics)
│ ├── dashboard/ # customer dashboard (points, shops, scanning)
│ └── ... # login, register, password reset, settings
├── components/ # shared UI components
├── lib/ # db pool, auth config, i18n, rate limiter
└── middleware.ts # route protection by role
- Passwords hashed with bcrypt; sessions are signed JWTs (
AUTH_SECRET) - Login endpoint rate-limited per IP (5 attempts / 15 min)
- Stamp QR tokens expire after a short window and are validated server-side
- Runs as a non-root user inside the Docker image
This project was built with an AI-assisted workflow: Claude Code, Anthropic's agentic CLI, running on the DeepSeek v4 Pro model — a deliberate choice driven by cost efficiency for a self-funded project, trading some raw capability for a dramatically lower iteration cost. I directed the process end to end: defining the product requirements, the multi-tenant data model, and the QR-based stamp/redemption flows; reviewing generated code; and testing each feature against a real PostgreSQL instance before it landed. The workflow's guardrails are visible in the repo itself — a reproducible Docker Compose environment, a seeded schema for instant verification, and CI that builds every push from a clean checkout. Working this way taught me as much about specifying and reviewing software rigorously as about writing it, and I consider fluency with AI development tools — including knowing when not to trust their output — a core part of my engineering practice.









