Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

123 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Dastiyab — Multi-Vendor E-Commerce Platform

A production-grade, multi-tenant marketplace built with Next.js 16. Vendors self-onboard and manage independent storefronts; customers browse, place orders, and track deliveries; admins govern the entire platform — all from a single codebase.

Think Shopify meets a regional marketplace — built ground-up on a modern React/Node stack.


Architecture Overview

┌─────────────────────────────────────────────────────────┐
│                     Next.js 16 App Router               │
├──────────────┬──────────────────────┬───────────────────┤
│  Customer    │   Vendor Dashboard   │    Admin Panel    │
│  Storefront  │   /store/* (SSR)     │  /admin/* (SSR)   │
│  /(public)/  │   TailAdmin UI       │  TailAdmin UI     │
├──────────────┴──────────────────────┴───────────────────┤
│         Auth.js v5  (JWT · Google OAuth · Credentials)   │
│              Role enforcement via Edge Middleware         │
├─────────────────────────────────────────────────────────┤
│          Prisma 7  +  PostgreSQL  (Docker / VPS)         │
├─────────────────────────────────────────────────────────┤
│           Cloudinary CDN  ·  Redux Toolkit (client)      │
└─────────────────────────────────────────────────────────┘

Three fully isolated role zones share one PostgreSQL schema and one deployment. Server Components handle all data fetching; Server Actions handle all mutations — zero REST endpoints in the admin/vendor layer.


Tech Stack

Concern Choice Notes
Framework Next.js 16.2.9 (Turbopack) App Router, RSC, Server Actions
Language React 19.2, Node 24, full ESM "type": "module" throughout
Styling Tailwind CSS v4 JIT, zero config
Back-office UI TailAdmin (Next.js) Components copied-in, not a runtime dependency
Auth Auth.js v5 (next-auth@beta) Google OAuth + Credentials; JWT strategy; Prisma adapter
ORM Prisma 7 + @prisma/adapter-pg Driver-adapter pattern; generated client in prisma/generated/
Database PostgreSQL Docker locally; any VPS Postgres in production
Image CDN Cloudinary Vendor product images; auth-gated upload endpoint
State (client) Redux Toolkit Cart, address, ratings — client-only slices
Testing Vitest 120 tests across 15 suites; unit + integration

Features

Customer Storefront

  • Product catalog with category filtering, search, and infinite scroll
  • Product detail pages with image gallery and computed star ratings
  • Persistent cart (Redux + DB sync — hydrates on login)
  • Checkout with saved delivery addresses and coupon validation
  • COD order placement and live order status tracking
  • Individual vendor store profile pages

Vendor Dashboard

  • Self-serve store creation and onboarding flow
  • Product management — create, edit, delete, toggle stock availability
  • Up to 4 Cloudinary-hosted product images per listing
  • Order management with status progression (Placed → Processing → Shipped → Delivered)
  • Revenue dashboard: earnings summary, product counts, recent customer ratings

Admin Panel

  • Platform KPIs: order volume, GMV, user counts, pending approvals
  • Store approval workflow — approve or reject vendor applications
  • Store activation toggle — suspend a live store instantly
  • User directory and role inspection
  • Coupon engine — percentage-off codes with expiry, audience targeting (new user / member / public)
  • Cross-platform order management and status overrides

Platform-Wide

  • Role-based access control enforced at the Edge (Next.js middleware) and server (lib/auth.js helpers)
  • All vendor data strictly scoped to session — storeId is always derived server-side, never accepted from the client
  • Shared Prisma singleton — no new PrismaClient() in route handlers
  • Cloudinary upload endpoint auth-gated to vendor and admin roles
  • Coupon validation enforces isPublic / forMember / forNewUser flags at both validate and order-placement endpoints

Data Model

User ──< Order (as buyer)
User ──  Store (1:1, vendor)
Store ──< Product
Store ──< Order
Order ──< OrderItem >── Product
Product ──< Rating
User ──< Rating
User ──< Address
Order >── Address
Coupon (standalone — validated at checkout)
Auth.js: Account, Session, VerificationToken

Selected schema decisions:

  • User.role (customer | vendor | admin) — single source of truth for RBAC, checked server-side on every protected route
  • Store.status (pending | approved | rejected) + Store.isActive — two-gate model separating onboarding approval from runtime suspension
  • Order.coupon Json — coupon snapshot embedded at order time, immune to future edits or deletions
  • User.cart Json — server-side cart fallback alongside Redux client state

Project Structure

app/
  (public)/         customer storefront — home, shop, product, cart, orders, create-store
  admin/            admin panel — dashboard, stores, approve, coupons, orders, users
    actions.js      all admin Server Actions (requireAdmin guard)
  store/            vendor dashboard — dashboard, add/edit/manage products, orders
    actions.js      all vendor Server Actions (requireVendor + ownership check)
  api/
    auth/           Auth.js handler + registration endpoint
    upload/         Cloudinary image upload (auth-gated)
    public/         customer-facing REST: products, categories, stores, coupons/validate
    customer/       authenticated REST: cart, addresses, orders, ratings, store

components/
  admin/            TailAdmin-based admin components
    ui/             shared primitives: StatCard, DataTable, Badge, PageHeader
  store/            vendor components (reuses admin/ui/ primitives)
  (public)/         storefront: Navbar, Footer, Hero, ProductCard, Banner

lib/
  prisma.js         shared Prisma client singleton
  auth.js           requireAdmin(), requireVendor(), getAuthUser() helpers
  cloudinary.js     Cloudinary SDK wrapper
  syncCart.js       fire-and-forget Redux ↔ DB cart sync
  features/         Redux slices: cartSlice, productSlice, addressSlice, ratingSlice
  store.js          Redux store

prisma/
  schema.prisma     canonical DB schema
  generated/        Prisma 7 generated client — do not edit
  migrations/       SQL migration files

__tests__/          Vitest test suites (120 tests, 15 files)
docs/               PRD, technical specs, implementation plans

Getting Started

Prerequisites

  • Node 24 (nvm use 24)
  • Docker (for local PostgreSQL)
  • Cloudinary account (free tier sufficient)
  • Google Cloud project with OAuth 2.0 credentials

1 — Clone and install

git clone https://github.com/jsoftsol/Dastiyab.git
cd Dastiyab
npm install

2 — Start PostgreSQL

docker compose up -d

3 — Environment variables

Copy .env.example to .env.local and populate:

DATABASE_URL=postgresql://user:password@localhost:5432/dastiyab

NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=<32-char random string — openssl rand -base64 32>

GOOGLE_CLIENT_ID=<from Google Cloud Console>
GOOGLE_CLIENT_SECRET=<from Google Cloud Console>

NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME=...
CLOUDINARY_API_KEY=...
CLOUDINARY_API_SECRET=...

4 — Push the schema and generate the Prisma client

npx prisma db push
npx prisma generate

5 — Run

npm run dev      # Turbopack dev server → http://localhost:3000

6 — Promote your account to admin

Sign in once with your email, then run:

UPDATE "User" SET role = 'admin' WHERE email = 'you@example.com';

Sign out and back in — you'll be routed to /admin.


Usage Guide

Customer

  1. Go to /sign-in — register with email/password or sign in with Google.
  2. Browse products at /shop — filter by category, search by name.
  3. Open a product to view details, images, and ratings; add it to your cart.
  4. Go to /cart to review items, then proceed to checkout.
  5. At checkout: add a delivery address, optionally apply a coupon code, and place a COD order.
  6. Track your orders at /orders; once an order is marked Delivered you can leave a star rating.

Vendor

Create a store

  1. Sign in (any account — customer role is the default).
  2. Go to /create-store and fill out the store form (name, description, etc.).
  3. Submit — the platform creates your store, upgrades your role to vendor, and signs you out automatically.
  4. Sign back in; you'll now have access to the vendor dashboard at /store.

Manage your store

Page Path What you can do
Dashboard /store Revenue summary, product counts, recent ratings
Add product /store/add-product Create a listing with up to 4 Cloudinary images
Manage products /store/manage-product Edit, delete, toggle in-stock
Orders /store/orders View orders and update status (Placed → Processing → Shipped → Delivered)

Note: Your store must be approved by an admin before products are visible to customers on the storefront.


Admin

Become an admin

  1. Sign in once to create your user record.
  2. Connect to the database and run:
UPDATE "User" SET role = 'admin' WHERE email = 'you@example.com';

With the local Docker setup:

docker exec -it gocart_db psql -U postgres -d gocart \
  -c "UPDATE \"User\" SET role = 'admin' WHERE email = 'you@example.com';"
  1. Sign out and sign back in — the JWT is refreshed with the new role.
  2. Go to /admin.

Admin capabilities

Page Path What you can do
Dashboard /admin Platform KPIs — orders, GMV, user count, pending approvals
Stores /admin/stores Toggle any store active / inactive
Approve /admin/approve Approve or reject pending vendor applications
Coupons /admin/coupons Create and delete coupon codes (percentage-off, expiry, audience targeting)
Orders /admin/orders View all orders across all stores; override status
Users /admin/users View all user accounts and their roles

Testing

npm test             # run all 120 tests
npm run test:watch   # watch mode
Suite Tests What is covered
smoke 2 env sanity
lib/auth 8 requireAdmin, requireVendor, getAuthUser
lib/cloudinary 3 upload helper
lib/prisma 2 singleton behaviour
api/register 4 registration endpoint, validation, duplicate email
api/upload 3 Cloudinary endpoint, auth guards
admin/actions 12 5 admin Server Actions — auth, enum validation, DB calls
store/actions 15 5 vendor Server Actions — auth, ownership enforcement
api/public/products 8 list with filters/pagination, detail with ratings
api/public/categories 3 distinct category list
api/public/stores 6 store lookup, store creation, vendor role update
api/public/coupons 8 validate endpoint — expiry, audience flags, auth-aware
api/customer/cart 4 GET (unauthed returns empty), PUT validation
api/customer/addresses 8 CRUD, ownership check on DELETE
api/customer/orders 7 multi-store transaction, address ownership, server-side prices
api/customer/ratings 7 DELIVERED check, duplicate prevention

Deployment

The project ships as a Docker multi-stage image behind a GitHub Actions workflow.

Docker

# Production stack (app + postgres + migrate)
docker compose -f docker-compose.prod.yml up -d

The Dockerfile uses three stages: deps (install), builder (Next.js build + prisma generate), runner (minimal production image). Next.js standalone output is used for a lean container.

CI/CD — GitHub Actions

Push to the deploy branch triggers .github/workflows/deploy.yml:

  1. rsync project files to VPS
  2. SSH: write .env.production, start postgres, run prisma migrate deploy, start app with --build
  3. Prune old Docker images

Required GitHub secrets: SERVER_HOST, SERVER_USER, SERVER_SSH_KEY, SERVER_APP_DIR, PRODUCTION_ENV

VPS pre-deploy checklist:

  1. Docker + Docker Compose v2 installed
  2. SSH key in ~/.ssh/authorized_keys
  3. $SERVER_APP_DIR/release/ directory exists
  4. All 5 secrets configured in GitHub repository settings

Build Roadmap

Phase Scope Status
0 Auth migration — Clerk → Auth.js v5 + Prisma adapter Complete
1 Foundation — PostgreSQL, Prisma 7, Cloudinary, middleware Complete
2 Admin Panel — TailAdmin UI + 6 pages + Server Actions Complete
3 Vendor Dashboard — 5 pages + Cloudinary upload + Server Actions Complete
4 Public Storefront — wire existing pages to real Prisma data Complete
5 Platform Services — coupon engine, product ratings Complete
Deployment — Docker, docker-compose.prod.yml, GitHub Actions CI/CD Complete

Engineering Decisions

Server Actions over REST for admin/vendor mutations. Keeps auth checks co-located with the mutation, eliminates a client/server serialization layer, and lets revalidatePath handle cache invalidation without a separate fetch. The pattern is consistent across both role zones: Server Component fetches → Server Action mutates → path revalidated.

Auth.js v5 over a managed auth service. Full ownership of the token shape and session callbacks, no third-party dependency, and clean self-hosting. JWT strategy avoids a session-table lookup on every request. Credentials + Google in a single config keeps onboarding flexible without managing two separate auth systems.

Prisma 7 driver adapter (@prisma/adapter-pg). The Prisma 7 mandated pattern for direct PostgreSQL connections. The generated client lives at prisma/generated/prisma/ — outside node_modules — making artefacts explicit, auditable, and version-controlled.

PostgreSQL over a managed database service. Direct connection keeps the local dev loop fast and removes a managed-DB dependency. The same schema deploys unchanged to any VPS Postgres instance, or migrates to RDS/Supabase with a connection string swap.

COD-only payments for now. Stripe is not available in all target markets. The schema carries a PaymentMethod enum (COD | STRIPE) so the integration can be added in a future phase without a breaking migration.

TailAdmin components copied-in, not installed as a package. Allows targeted per-component modifications without fighting an upstream update cycle. Both the admin and vendor zones share a common primitive layer (components/admin/ui/) so changes propagate to both surfaces.


Contributing

Pull requests are welcome. Please open an issue first to discuss substantial changes. See CONTRIBUTING.md for guidelines.


License

MIT — see LICENSE.md.

About

Multi-vendor e-commerce marketplace built with Next.js 16 — vendors manage stores, customers shop with COD checkout, admins oversee the platform.

Topics

Resources

Code of conduct

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages