Skip to content

alisheikh2/ShopFlowAI

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

38 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ›οΈ ShopFlowAI

A full-stack, AI-assisted e-commerce platform built solo β€” from checkout reliability to admin operations.

Live Node.js React MongoDB Stripe Redis CI

πŸ”— Live: shopflowai.me

Features β€’ Tech Stack β€’ Getting Started β€’ Architecture β€’ Testing β€’ Live Demo


πŸ“– Overview

ShopFlowAI is a production-style e-commerce SaaS platform covering the full lifecycle of an online store β€” customer browsing and checkout, Stripe payments, and a complete admin back office β€” built with a deliberate focus on the problems that break real systems in production: overselling, duplicate webhook events, dead sessions, and inconsistent state after a crash mid-transaction.

It was designed and built end-to-end by a single developer as a deep dive into full-stack engineering, distributed-systems thinking, and production-readiness β€” not just "does the feature work," but "does it hold up under failure."

🌍 Live Demo

https://www.shopflowai.me

The app is deployed and publicly accessible β€” frontend on Vercel, backend API on a Node host, MongoDB on Atlas. Stripe is running in test mode, so you can walk through the full checkout flow without a real card:

Field Value
Card number 4242 4242 4242 4242
Expiry Any future date
CVC Any 3 digits

✨ Features

πŸ›’ Customer Experience

  • Browse, search, and filter products by category
  • Cart & wishlist, with persistent state across sessions
  • Secure Stripe checkout using Stripe Elements (no raw card data ever touches the server)
  • Google Sign-In via Firebase, alongside standard email/password auth
  • Email verification, password recovery, and account-recovery flows
  • Order tracking, downloadable PDF invoices, and product reviews

πŸ› οΈ Admin Dashboard

  • Revenue and sales analytics
  • Product & category management, with Cloudinary image uploads
  • AI-generated product descriptions when creating/editing products (Gemini API)
  • Order management β€” update fulfillment status, issue refunds, export invoices
  • User management β€” search, filter, paginate; change roles; ban/unban accounts with immediate session termination

βš™οΈ Engineering Highlights

  • Inventory reservation system β€” stock is held (not deducted) during checkout and auto-released if payment never completes, preventing overselling
  • Idempotent Stripe webhooks β€” duplicate events are detected and safely ignored, with amount/currency/order cross-checks
  • Outbox pattern for refunds and media cleanup, so a crash mid-transaction never leaves the database pointing at something that no longer exists
  • Hashed refresh tokens (SHA-256, unique jti) β€” a database leak alone can't be used to hijack a session
  • In-memory access tokens with automatic, deduplicated silent refresh β€” nothing sensitive sits in localStorage
  • Redis caching for products, categories, and analytics
  • Rate limiting, input validation, and centralized error handling across every module

🧰 Tech Stack

Layer Technology
Frontend React 19, Vite, React Router
Backend Node.js, Express
Database MongoDB (Mongoose), replica-set transactions
Caching Redis
Payments Stripe (Elements, webhooks, idempotency)
Auth JWT (access + refresh), Firebase Google Sign-In
Media Cloudinary
AI Google Gemini API
Email Resend (HTTPS API)
Testing Node.js test runner, mongodb-memory-server, Vitest
CI/CD GitHub Actions (lint β†’ test β†’ build β†’ audit)

πŸš€ Getting Started

Prerequisites

  • Node.js 22.12+ (nvm use)
  • Docker (for a local MongoDB replica set β€” required for transactions)

1. Start local infrastructure

docker compose up -d mongo
docker compose ps          # wait for the health check (initializes replica set rs0)

# optional Redis cache
docker compose --profile cache up -d

2. Configure environment variables

cp server/.env.example server/.env
cp client/.env.example client/.env

Fill in your MongoDB, JWT, Resend, Stripe, Cloudinary, Gemini, and Firebase credentials. Never commit .env or Firebase service-account JSON.

3. Install & run

cd server && npm ci && npm run dev
# in a second terminal
cd client && npm ci && npm run dev
Service URL
Frontend http://localhost:5173
API health check http://localhost:5000/api/v1/health

πŸ—οΈ Architecture Highlights

πŸ’³ Payment lifecycle (click to expand)

Stripe checkout uses a bounded inventory reservation and idempotent payment flow:

  1. The client sends a UUID checkoutId; duplicate order requests return the same order.
  2. POST /orders reserves inventory for Stripe but keeps cart items until payment succeeds.
  3. The reservation expires after PAYMENT_RESERVATION_MINUTES (default 30).
  4. POST /payments/create-intent snapshots the exchange rate, USD minor amount, and currency, and uses a Stripe idempotency key.
  5. Signed webhooks are stored once by Stripe event ID and must match order ID, user ID, PaymentIntent ID, amount, and currency.
  6. A success webhook commits inventory, marks the order paid/processing, removes purchased cart items, and sends paid invoice/notifications.
  7. Failed card payments remain retryable until reservation expiry.
  8. Expired/cancelled reservations restore stock and queue PaymentIntent cancellation.
  9. Late payment after cancellation never revives the order; it queues an idempotent refund.
  10. Refunds run through a Mongo-backed outbox (OutboxEvent) rather than inside Mongo transactions.
  11. Cloudinary image replacement/deletion is also queued through the outbox so DB state never points at an image deleted before commit.

The API process starts the commerce worker automatically. For a separate scheduled worker, set DISABLE_COMMERCE_WORKER=true on API instances and run:

cd server
npm run worker:once

Run it every 30–60 seconds via your process manager/scheduler. Multiple workers are safe β€” events are atomically claimed and Stripe calls use idempotency keys.

πŸ” Session security (click to expand)
  • Access tokens live only in browser memory; legacy localStorage tokens are removed automatically.
  • The HttpOnly refresh cookie restores a session after reload.
  • One failed authenticated request performs a single deduplicated refresh and retries once.
  • Refresh tokens are stored as SHA-256 hashes in MongoDB with a unique JWT jti.
  • Existing raw refresh-token sessions migrate automatically on their next rotation/logout.
  • Banned users are rejected immediately β€” even with a still-valid access token β€” and lose all active sessions the moment they're banned.
πŸ—„οΈ Upgrading an existing database (click to expand)

Back up MongoDB first, deploy with the commerce worker disabled, then run once:

cd server
npm run migrate:phase1   # marks legacy inventory state, snapshots Stripe amounts
npm run migrate:phase2   # hashes any legacy raw refresh tokens (idempotent)

Fresh databases do not need either step.

πŸ”₯ Firebase Admin setup (click to expand)

The adapter resolves credentials in this order:

  1. FIREBASE_SERVICE_ACCOUNT_JSON env var β€” a stringified service-account JSON, used in production (Render/Vercel/etc. where dropping a local file isn't practical).
  2. Fallback: a local file at server/src/config/firebase/shopflowai-firebase-adminsdk.json β€” used for local development. That path is gitignored; download the service-account file from Firebase console.

πŸ§ͺ Testing & CI

# Client
cd client
npm run lint
npm test
npm run build

# Server
cd server
npm test

GitHub Actions runs this full pipeline β€” lint, test, build, and npm audit β€” on every push and pull request to main. See .github/workflows/ci.yml.

Server integration tests run against a real in-memory MongoDB replica set (via mongodb-memory-server), so transactional flows (checkout, reservations, refunds) are tested against real Mongo transaction semantics β€” not mocks.

Stripe local webhook testing
stripe listen --forward-to localhost:5000/api/v1/payments/webhook

Copy the CLI webhook secret to STRIPE_WEBHOOK_SECRET. Use Stripe test mode only.

πŸ“ Project Structure

ShopFlowAI/
β”œβ”€β”€ client/                 # React 19 + Vite frontend
β”‚   └── src/
β”‚       β”œβ”€β”€ pages/          # Route-level views (customer + admin)
β”‚       β”œβ”€β”€ components/     # Shared UI components
β”‚       β”œβ”€β”€ contexts/       # Auth, Cart, Wishlist, Toast providers
β”‚       └── services/       # API client, Stripe, Firebase
β”œβ”€β”€ server/                 # Express + MongoDB backend
β”‚   └── src/
β”‚       β”œβ”€β”€ controllers/    # Route handlers
β”‚       β”œβ”€β”€ services/       # Business logic (orders, payments, reservations…)
β”‚       β”œβ”€β”€ models/         # Mongoose schemas
β”‚       β”œβ”€β”€ middleware/     # Auth, validation, rate limiting, error handling
β”‚       └── routes/         # API route definitions
β”œβ”€β”€ docker-compose.yml       # Local MongoDB replica set + optional Redis
└── .github/workflows/ci.yml # Lint β†’ test β†’ build β†’ audit pipeline

🌐 Deployment Notes

  • Use Node 22.12+ on all API, worker, build, and CI machines.
  • Use MongoDB Atlas or a production replica set β€” never deploy a standalone MongoDB (transactions require a replica set).
  • Run at least one commerce worker continuously.
  • Redis is used for response caching only (products, categories, analytics) β€” rate limiting is in-memory per instance (express-rate-limit), so it resets per process and isn't shared across horizontally-scaled API instances yet.
  • Configure Stripe webhooks with the raw request body and HTTPS.
  • Back up and monitor the orders, stripeevents, and outboxevents collections.
  • Alert on failed outbox events and refundStatus: failed.

πŸ‘€ Author

Ali Hassan BS Computer Science, COMSATS University Islamabad (Sahiwal Campus)


Built as an independent, production-style engineering project β€” not a tutorial clone.

About

A modern AI-powered MERN e-commerce platform with Stripe payments, Firebase authentication, Cloudinary image uploads, admin dashboard, analytics, and Gemini AI integration.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages