Skip to content
CASE STUDY

GTaugment AR

AR-powered merch catalogues · NestJS · Next.js · Prisma

Impact: Three payment gateways, three cloud storage providers, and three currencies behind a single subscription API — businesses onboard in NG/US/RU markets without code changes.

NestJS · Next.js 15 · TypeScript · Prisma · PostgreSQL · MUI · Redux Toolkit · Socket.IO · Cloudinary · AWS S3 · PayPal · Paystack · YooMoney · Docker
GTaugment AR album view
GTaugment AR business dashboard
GTaugment AR QR-code share flow

Problem

Small merchants and creators wanted product pages that felt richer than flat e-commerce listings — short demo videos, 3D views, scannable in-store QR codes — but every off-the-shelf path forced a trade-off. Shopify and similar platforms offered the storefront but no AR primitives; standalone AR tools offered the media but no commerce, payments, or analytics. Worse, the audience spanned Nigeria, the US, and Russia, so a one-payment-gateway-fits-all approach (the default for most SaaS) would lock out two of three markets at sign-up.

Approach

  • 01

    Modelled the AR album as a first-class entity, not a media attachment. Albums have their own ID space, view counters, ratings, embedded CTA buttons, and QR codes — so the same record can power an in-store scan, an Instagram link, and an in-app feed without duplicating logic.

  • 02

    Made the payment gateway a runtime decision, not a config flag. A user’s country drives currency, currency drives gateway (Paystack → NGN, PayPal → USD, YooMoney → RUB), and the subscription service hands the right adapter to the checkout flow — so adding a new market is one adapter, not a checkout rewrite.

  • 03

    Abstracted storage behind a single upload interface backed by a DB-stored provider setting. Ops can flip from Cloudinary to S3 to GCS by updating one row; the upload pipeline reads StorageSetting and dispatches accordingly. Kept the team from getting locked into Cloudinary’s pricing early.

  • 04

    Used JWT request-type tagging instead of separate token endpoints. One JWT structure carries a requestType (LOGIN, USER_VERIFICATION, BUSINESS_VERIFICATION, REQUEST_RESET_PASSWORD, RESET_PASSWORD) so the same auth guard handles every flow — fewer code paths, fewer ways to misroute a token.

  • 05

    Built the marketing site, customer app, and backend as three separable deployables. The Next.js marketing site ships independently from the customer-facing Next.js app and the NestJS API, so content changes do not require a backend deploy.

Outcome

  • 01

    Single platform serves NG/US/RU merchants natively — no "we do not accept your card" wall at checkout.

  • 02

    Album media stays portable: storage provider can be swapped without code changes, which decoupled vendor pricing risk from feature velocity.

  • 03

    AR album + QR pattern doubles as both an online product page and an in-store scan target, so one upload powers two distribution channels.

  • 04

    Led a CapacityDey team of 20 to ship API, customer app, and marketing site as three independently deployable surfaces.

Lessons

  • 01

    Make money flows pluggable from day one, even if you launch with one gateway. Retrofitting multi-currency, multi-gateway logic into a system already wired to Stripe is painful; designing the subscription/payment layer around a paymentGateway enum and country-derived currency from the start cost about a week and unlocked two markets.

  • 02

    Do not let your storage SDK leak into business logic. Wrapping Cloudinary/S3/GCS behind one uploadFile(file, path) interface kept the album, catalogue, and advertisement modules indifferent to where bytes actually live — and made the "what if Cloudinary doubles pricing" conversation a one-day migration instead of a quarter.

  • 03

    One JWT shape with a requestType discriminator beats five purpose-specific tokens. Every "send a token in an email" flow (verify, reset, invite) collapses into the same guard plus a switch — fewer endpoints to audit, fewer mistakes around token reuse.