Home/Our Work/Loyalty Club PLC

Loyalty Club PLC

Enterprise-grade loyalty platform with a revolutionary digital token system for reward exchanges.

Visit live site ↗

Loyalty Club PLC needed a robust platform that goes beyond traditional points — featuring a revolutionary digital token for seamless reward exchanges between partners and customers.

Lucid Code Labs engineered the experience end to end — from information architecture and UI through to the token-based reward system and scalable backend.

We also developed a companion mobile app so users can earn, exchange, and redeem rewards wherever they are.

The platform supports growth with a codebase and design system the team can evolve confidently.

SaaSMobile appProduct designFull-stack delivery

The challenge

Loyalty Club PLC set out to build a loyalty platform that goes beyond traditional points, centred on a digital token that lets rewards be exchanged between partners and customers. That premise changes the engineering problem: reward value has to behave like a transferable balance with a proper audit trail, not like a counter held inside one merchant's scheme. The platform also had to carry the day-to-day operations partners and members depend on, and reach members through a companion mobile app so they can earn, exchange and redeem wherever they are. Underneath all of it, the client needed a codebase and design system their team could keep extending with confidence.

Our approach

  • Lucid Code Labs engineered the product end to end, from information architecture and interface design through to the token-based reward system and the backend that runs it.
  • The backend is a Node.js and Express REST API on MongoDB Atlas, using Mongoose discriminators and refPath references to model the many user types the network involves, with Agenda handling recurring work; at the time of writing it spans 382 route handlers across 22 Express routers and 34 model files, deployed on Render with a SIGTERM handler that stops the job scheduler before closing the HTTP listener.
  • Reward value is recorded in a custom double-entry wallet ledger rather than as simple point counters, so every stamp exchange, token purchase, donation, booking payment and refund exists as a typed transaction between two wallets.
  • Customer-facing card payments for bookings and menu orders run on Square through partner-owned OAuth connections, so those funds move from customer to partner rather than through the platform, with partner tokens encrypted at rest using AES-256-GCM and refreshed by a nightly job.
  • The same API serves the member, partner and agent portals and the companion mobile app, whose Capacitor origins sit in the CORS allowlist, and it issues signed Apple Wallet passes and Google Wallet save links so a loyalty card can live on the phone itself.

What we built

TEDS closed-loop token currency

Reward value is held in a double-entry wallet ledger where each TEDS transaction records one of 15 transaction types, from token purchase and stamp exchange to cause donations, booking payments and order refunds, with source and destination wallet references and polymorphic user references across nine user types. Members exchange stamps for TEDS, partners can link a bank account to cash out and administrators approve pending transactions, while nightly Agenda jobs aggregate wallet activity and record daily totals.

One stamp engine behind every visit

A single shared awardStampsForVisit routine serves the QR and till flow, the QR menu-order flow and the booking attendance flow, so a stamp is awarded identically however the customer arrives. Campaigns support Buy X, Get Y Free and Spend X Amount To Earn a Stamp, with goals, start and end dates, QR enrolment and referrer rewards, and side effects such as review asks and referrals are individually caught so a failure there can never cost a customer their stamp.

QR table ordering and menu management

Menus model day and time schedules, sections, items and reusable modifier groups for build-your-own dishes, with the UK's 14 regulated allergens enforced as a schema enum. Guests order from a QR short code without an account, partner endpoints cover the kitchen board, mark-paid, settle-at-till and write-off, and the order controller enforces an explicit received to accepted to in_progress to completed state machine, alongside cancel and reject paths, returning HTTP 409 on an illegal transition.

A booking engine guarded by one unique index

Availability is computed on read against a five-minute grid instead of materialising slots, and the only persisted artefact is a SlotLock whose unique compound index on client, resource and cell start makes two overlapping bookings collide at the database rather than in application code, with no multi-document transactions required and a TTL index automatically freeing abandoned holds. Working hours are stored as local times and converted per date with date-fns-tz so daylight-saving days stay correct, and the engine handles both appointment mode and table mode.

Partner-owned Square payments

A full Square OAuth handshake with signed state connects each partner's own Square account, keeping booking and order payments out of the platform's flow of funds, and access and refresh tokens are encrypted at rest with AES-256-GCM using a random IV and stored auth tag. Scheduled jobs refresh those tokens nightly and release unpaid bookings and menu orders every fifteen minutes, while a currency utility normalises stored symbols to ISO 4217 codes before anything reaches a payment API.

Two AI-assisted features

Photographed menus are read into structured sections and dishes using OpenAI vision with strict json_schema Structured Outputs and then re-validated, recording allergens and dietary tags only where the printed menu states them because inferring an allergen is a regulatory exposure; where no API key is configured the feature reports itself as unconfigured rather than failing obscurely. A second service grades open-ended sales training answers against the training content and returns written feedback, falling back to manual review if grading is unavailable. Both default to gpt-4o-mini and are model-configurable by environment.

Technology

Runtime & API

  • Node.js 20
  • Express 4.18
  • express-async-handler
  • EJS (server-rendered password-reset views)
  • ESLint 8
  • nodemon

Data & Persistence

  • MongoDB Atlas
  • Mongoose 6.8 (discriminators and refPath polymorphic refs)
  • mongoose-paginate-v2
  • GridFS (image and document storage)
  • MongoDB 2dsphere geospatial indexes
  • Agenda 5 (MongoDB-backed job store)
  • node-schedule

Payments, Commerce & AI

  • Square SDK v38 (subscriptions, checkout links, OAuth Connect)
  • Square webhooks with raw-body HMAC verification
  • Stripe (subscription billing)
  • svix (inbound webhook signature verification)
  • TEDS internal token ledger (custom double-entry wallet model)
  • openai SDK v6 (gpt-4o-mini default, Structured Outputs and vision)
  • date-fns / date-fns-tz

Messaging, Media & Wallets

  • firebase-admin (FCM push, including multicast)
  • Resend (transactional email and inbound email webhook)
  • Brevo REST API (lifecycle and marketing email)
  • Cloudflare R2 via @aws-sdk/client-s3
  • sharp
  • heic-convert
  • passkit-generator (Apple Wallet .pkpass)
  • qrcode and multer

Security

  • helmet 8 with per-request CSP nonce
  • express-rate-limit 7 (tiered limiters)
  • jsonwebtoken (role-scoped bearer JWTs)
  • bcryptjs / bcrypt
  • AES-256-GCM token encryption (node crypto)
  • CORS origin allowlist including capacitor:// schemes

Project Gallery

Loyalty Club PLC platform — primary view
Product overview and key interface.
Loyalty Club PLC platform — feature section
Core flows and layout.
Loyalty Club PLC platform — additional screen
Further views and responsive treatment.
← All our work