Skip to content

Repository files navigation

QuickStamp

QuickStamp

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

CI


Requirements

  • Docker with Compose — that's all for running the app
  • Node.js ≥ 20.9 — only for local development

Features

  • 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

Screenshots

Screenshot 1 Screenshot 2 Screenshot 3 Screenshot 4 Screenshot 5
Screenshot 6 Screenshot 7 Screenshot 8 Screenshot 9 Screenshot 10

Tech Stack

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

Quick Start

cp .env.sample .env      # edit with secure values
docker compose up -d     # PostgreSQL + app on http://localhost:3000

Default admin account: admin@quickstamp.local / admin123change this after first login.

Optional pgAdmin console:

docker compose --profile tools up -d   # pgAdmin on :5050

Development

cp .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:3000

The 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 run npm run dev:https.

How It Works

  1. A shop registers and is approved by the platform admin.
  2. Staff open the shop dashboard and generate a QR code — each code is valid for a short window.
  3. The customer scans the code with their phone and a point is added to their balance at that shop.
  4. When enough points accumulate, the customer taps Redeem — this produces a redemption QR.
  5. Staff scan the redemption QR to confirm the free drink, closing the loop.

Database Schema

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 staff
  • points — point ledger per customer per shop
  • rewards — redemptions with verification tokens

Schema is initialized automatically from sql/init.sql on first startup.

Project Structure

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

Security Notes

  • 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

Development Process

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.

License

MIT

About

Self-hosted multi-tenant coffee shop loyalty platform — short-lived QR stamps, points, and reward redemption. Next.js 16 + PostgreSQL.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages