Elite Cuts
Full-stack e-commerce app — TypeScript redesign with auth, Stripe, and a loyalty engine

Full-stack butcher-shop e-commerce app built with Next.js, MongoDB, NextAuth.js, and Stripe — a TypeScript redesign with a three-tier loyalty program, admin dashboard, and five pricing models.
Problem
A prior JavaScript version of the app existed but lacked type safety, a real auth system, Stripe payments, and any product logic beyond basic CRUD. It needed a proper full-stack redesign.
Goal
Redesign the app in TypeScript strict mode — end-to-end type safety from Mongoose schema through Zod validation through API routes through React components — and ship a vertically integrated e-commerce system with auth, payments, inventory, and a loyalty engine.
What I Built
A fictional premium butcher-shop storefront (portfolio demo, no real orders). 39 products across 9 categories, five pricing models that all have to render correctly in browse, cart, and admin, and a checkout that works signed in or as a guest — with guest orders claimable into a new account by registering the same email. The spine is order-before-redirect plus an idempotent Stripe webhook that settles payment, stock, loyalty points, and promo usage in one pass.
Key Features
- Stripe Checkout with pickup-time scheduling — order written before redirect, settled by an idempotent webhook
- Guest checkout with order claiming — registering with the email from a guest order pulls it into the new account
- One-click seeded demo accounts at /demo — no password sent to the browser, state restored nightly by a bearer-gated cron
- Three-tier loyalty program — rolling 12-month qualification, point earn/redeem, refund reversal
- Five pricing models (fixed, per-pound, whole, individual, bundle) with display labels across cart, checkout, and admin
- NextAuth.js credentials provider with JWT sessions carrying custom userId and admin claims
- Middleware-enforced RBAC — admin dashboard routes protected server-side
- Full admin dashboard — product CRUD with Cloudinary uploads plus orders, customers, inventory, promos, analytics, messages, schedule, staff, and settings tabs with CSV import/export
- Cart with price snapshots — prevents stale pricing between browse and checkout
- 39-product paginated catalog with search, sort (Featured / Price asc-desc / Newest), and category + stock filters
- Product image gallery via PhotoSwipe on detail pages
- Vitest test suite with npm test and typecheck commands
Challenges
- Designing five distinct pricing types that render correctly across browse, cart, admin, and Stripe line items
- Idempotent Stripe webhook settlement — order written before redirect, so a retried webhook can never double-apply stock, points, or promo usage
- MongoDB schema decisions: embedded addresses in user documents vs. referenced; cart price snapshots to prevent stale-price bugs
- Carrying custom JWT claims (userId, admin) through NextAuth without breaking TypeScript strict mode inference
- Migrating from the original JavaScript app to strict TypeScript without regressing any feature
Outcome
Live on Vercel with one-click demo accounts. Full checkout flow operational in Stripe test mode. Three-tier loyalty program fully modeled. Admin dashboard covering all ten operational areas. TypeScript strict mode throughout with zero any types; Vitest suite run across three timezones.