惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - 司徒正美
大猫的无限游戏
大猫的无限游戏
腾讯CDC
J
Java Code Geeks
博客园 - 【当耐特】
Microsoft Azure Blog
Microsoft Azure Blog
V
Visual Studio Blog
人人都是产品经理
人人都是产品经理
博客园 - Franky
博客园 - 聂微东
阮一峰的网络日志
阮一峰的网络日志
美团技术团队
云风的 BLOG
云风的 BLOG
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
U
Unit 42
雷峰网
雷峰网
B
Blog RSS Feed
博客园_首页
量子位
F
Fortinet All Blogs
罗磊的独立博客
H
Hackread – Cybersecurity News, Data Breaches, AI and More
酷 壳 – CoolShell
酷 壳 – CoolShell
C
Check Point Blog

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
Building a Multi-Vendor Marketplace From Scratch: Lessons...
Faizullah · 2026-06-19 · via DEV Community

Faizullah

Building a Multi-Vendor Marketplace From Scratch: Lessons From 30,000 Lines of React

By Faiz Ullah — Full-Stack Developer & Founder of DG Technology


Most "build an e-commerce site" tutorials stop at a product list and a cart. They don't deal with the actual hard part: three different types of humans — customers, sellers, and admins — all needing their own secure space inside the same app, talking to each other in real time, without ever stepping on each other's data.

That's what I set out to build with Ecommerce, a multi-vendor marketplace that grew to over 30,000 lines of React. Here's what I learned engineering it.


The Real Challenge: Three Apps in One

A single-vendor store is one application. A multi-vendor marketplace is really three applications sharing a database:

  • Customers browse, buy, and chat with sellers
  • Sellers manage their own storefront, fulfill orders, and request payouts
  • Admins oversee everyone — approving sellers, resolving disputes, releasing payouts

The temptation is to bolt all three onto one App.js with a bunch of if (userType === 'admin') checks scattered everywhere. That gets unmanageable fast. Instead, I built three fully independent authentication systems, each with its own protected route guard:

<Route element={<ProtectedCustomerRoute />}>...</Route>
<Route element={<ProtectedSellerRoute />}>...</Route>
<Route element={<ProtectedAdminRoute />}>...</Route>

Each guard checks its own session state independently. A seller session can never accidentally leak into the admin view, even if someone tries to manipulate the URL directly.


Real-Time Chat Without a Custom Server

I wanted buyers and sellers to message each other live — no page refresh, no polling. Rather than standing up a WebSocket server, I leaned on Firestore's real-time listeners, which turned out to be the right call for a project this size:

onSnapshot(query(messagesRef, orderBy('timestamp')), (snapshot) => {
  // UI updates instantly as new messages arrive
});

This single pattern powers chat, unread-message counts, and live presence — all without me managing a single socket connection.


The Presence Problem

Showing whether a seller is "online" sounds trivial until you actually build it. A simple isOnline: true flag breaks the moment someone closes their laptop without logging out — they stay "online" forever.

The fix is a heartbeat pattern: the seller's client writes a lastSeen timestamp every few seconds while the tab is active, and stops the moment the tab closes or loses visibility:

document.addEventListener('visibilitychange', () => {
  if (document.hidden) stopHeartbeat();
  else startHeartbeat();
});

Anyone viewing the seller's profile just checks: was the last heartbeat recent? No server-side cron job needed, no stale "online" ghosts.


Media at Scale: Don't Make Your Database Hold Images

Early on I made the rookie mistake of storing image data directly. That doesn't scale — Firestore documents have size limits, and serving large base64 blobs kills load times.

The fix was routing all uploads through Cloudinary, using unsigned upload presets so the API secret never has to live in client-side code:

formData.append('upload_preset', cloudinaryConfig.uploadPreset);
const res = await fetch(`https://api.cloudinary.com/v1_1/${cloudName}/upload`, {
  method: 'POST', body: formData
});

Cloudinary then handles resizing, format conversion, and CDN delivery — the database only ever stores a URL.


The Payout Problem Nobody Talks About

Letting sellers earn money is the easy half. Letting them withdraw it safely is the half that actually matters. I built a dedicated WithdrawalRequestsManager so that:

  1. A seller requests a withdrawal
  2. The request enters a pending queue — funds are not released automatically
  3. An admin reviews and approves it manually before money moves

This manual checkpoint is deliberate. Automating payouts sounds efficient until the first fraud attempt — a human review step at the money boundary is the cheapest fraud prevention you can build.


What I'd Tell Someone Building Their First Marketplace

  • Separate your three user types from day one. Retrofitting role isolation onto a single auth system later is painful.
  • Use your database's real-time features before reaching for a custom server. Firestore's listeners replaced what would have been a whole separate real-time service.
  • Never store binary media where structured data lives. Offload it to dedicated media infrastructure immediately.
  • Put a human checkpoint wherever money actually leaves the system.

The Stack

Layer Technology
Frontend React, React Router
UI Material UI (MUI)
Database Firebase Firestore
Auth Firebase Authentication
Realtime DB Firebase Realtime Database (presence)
Media Cloudinary

Faiz Ullah
Full-Stack Developer · Founder of DG Technology
🌐 faizullah.pk · 💻 github.com/faizullahpk/multivendor-marketplace


If you're building something with multiple user roles and real-time data, I'd love to hear about it — follow along for more on shipping real-world full-stack systems.