Build a multi-seller marketplace using Firestore collections for sellers, products, and orders. Buyers browse products across all sellers with category and price filters in a GridView. Sellers manage their own storefront via a dashboard with product CRUD, sales stats, and earnings summary. Payments use Stripe Connect to split each transaction between the platform fee and seller payout. Add buyer-seller messaging for order questions.
Multi-seller marketplace with storefronts, split payments, and messaging
A marketplace connects multiple sellers with buyers, with the platform taking a commission on each sale. This tutorial builds the full system: sellers create storefronts and list products, buyers browse all products with filters and purchase via Stripe Connect (which splits payment between the platform and seller), and orders track status from placed to delivered. In-app messaging connects buyers and sellers for questions about products or orders. Unlike a single-store e-commerce app, this handles multiple sellers, each with their own inventory and earnings.
Prerequisites
- A FlutterFlow project with Firebase/Firestore connected
- Stripe account with Stripe Connect enabled (Express accounts)
- Cloud Functions enabled (Firebase Blaze plan)
- Firebase Authentication with user accounts
- Basic understanding of Backend Queries and Action Flows in FlutterFlow
Step-by-step guide
Set up Firestore collections for sellers, products, and orders
Set up Firestore collections for sellers, products, and orders
Create a sellers collection with fields: userId (String), storeName (String), storeDescription (String), logoUrl (String), rating (Double, default 0), reviewCount (Integer, default 0), isVerified (Boolean, default false), and stripeAccountId (String — their Stripe Connect account). Create a products collection: sellerId (String), name (String), description (String), price (Double), images (List of Strings), category (String), status (String — active, sold, paused), and createdAt (Timestamp). Create an orders collection: buyerId (String), sellerId (String), productId (String), productName (String), total (Double), commission (Double — platform fee), sellerPayout (Double), status (String — placed, shipped, delivered, cancelled), and timestamp (Timestamp). Set Firestore rules: sellers can CRUD their own products; buyers can read all products and create orders; only Cloud Functions update order financials.
Expected result: Firestore has sellers, products, and orders collections with proper security rules for multi-seller access.
Build the buyer browse experience with product grid and seller profiles
Build the buyer browse experience with product grid and seller profiles
Create a BrowsePage with a GridView (crossAxisCount: 2) bound to a Backend Query on products where status == active. Add a DropDown for category filter and a Slider for price range at the top. Each product card shows: Image (first from images array), Text (name), Text (price formatted as currency), and a small Row with the seller's storeName (query sellers where userId == product.sellerId). On Tap, navigate to ProductDetailPage showing full images in a PageView, description, price, seller info card (storeName + rating stars + reviewCount), and a Buy Now button. Add a Seller Profile link that navigates to SellerStorePage filtered to that seller's products with their store banner, description, and all active listings.
Expected result: Buyers can browse all marketplace products with filters, view product details with seller info, and visit individual seller storefronts.
Create the seller dashboard with product management and analytics
Create the seller dashboard with product management and analytics
Create a SellerDashboardPage gated behind a role check (only users with a sellers document). Use a TabBar with three tabs: Products, Orders, and Earnings. Products tab: ListView of the seller's products (where sellerId == currentUser.uid) with each row showing thumbnail, name, price, status badge, and Edit/Delete IconButtons. Add a FAB to navigate to AddProductPage — a form with TextFields for name, description, price, DropDown for category, and FlutterFlowUploadButton for images (up to 5). Edit updates the existing document; delete sets status to paused (soft delete). Orders tab: ListView of orders where sellerId == currentUser.uid showing buyer name, product, status DropDown for updating fulfillment. Earnings tab: Container cards showing total revenue, platform commission, and net payout calculated from orders query.
Expected result: Sellers can list products, manage inventory, update order statuses, and view their earnings — all from a dedicated dashboard.
Integrate Stripe Connect for split payments
Integrate Stripe Connect for split payments
Each seller needs a Stripe Connect Express account. Deploy a Cloud Function onboardSeller that calls stripe.accounts.create({type: 'express'}) and returns the onboarding URL. On the seller dashboard, add a Connect Stripe button that calls this function, saves the returned stripeAccountId to the seller document, and opens the Stripe onboarding URL via Launch URL. For purchases, deploy a Cloud Function createMarketplaceCheckout that creates a Stripe Checkout Session with payment_intent_data.application_fee_amount set to your platform commission (e.g., 10% of product price) and transfer_data.destination set to the seller's stripeAccountId. The buyer clicks Buy Now, the Cloud Function returns the checkout URL, and Launch URL opens Stripe's payment page. On checkout.session.completed webhook, create the order document with total, commission, and sellerPayout calculated.
1// Cloud Function: createMarketplaceCheckout2const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);34exports.createMarketplaceCheckout = async (req, res) => {5 const { productName, price, sellerStripeAccountId, buyerId, sellerId, productId } = req.body;6 const commission = Math.round(price * 10); // 10% in cents7 const session = await stripe.checkout.sessions.create({8 payment_method_types: ['card'],9 line_items: [{10 price_data: {11 currency: 'usd',12 product_data: { name: productName },13 unit_amount: Math.round(price * 100),14 },15 quantity: 1,16 }],17 mode: 'payment',18 payment_intent_data: {19 application_fee_amount: commission,20 transfer_data: { destination: sellerStripeAccountId },21 },22 metadata: { buyerId, sellerId, productId },23 success_url: 'https://yourapp.com/order-success',24 cancel_url: 'https://yourapp.com/product/' + productId,25 });26 res.json({ url: session.url });27};Expected result: Payments split automatically: the platform keeps its commission and the seller receives their payout via Stripe Connect.
Add buyer-seller messaging for order inquiries
Add buyer-seller messaging for order inquiries
Create a messages subcollection under each order document: orders/{orderId}/messages with fields senderId (String), text (String), and timestamp (Timestamp). On the order detail page (accessible to both buyer and seller), add a ListView bound to the messages subcollection ordered by timestamp ascending with Single Time Query OFF for real-time updates. Style messages as chat bubbles: right-aligned blue for the current user, left-aligned grey for the other party. Pin a TextField + Send button at the bottom. The Send action creates a message document and updates a lastMessageTime field on the order for sorting. Restrict Firestore rules: only the buyer (buyerId) and seller (sellerId) of that order can read/write messages.
Expected result: Buyers and sellers can message each other in real time within the context of a specific order.
Complete working example
1Firestore Data Model:2├── sellers/{sellerId}3│ ├── userId: String4│ ├── storeName: String ("Jane's Handmade")5│ ├── storeDescription: String6│ ├── logoUrl: String7│ ├── rating: Double (4.7)8│ ├── reviewCount: Integer (23)9│ ├── isVerified: Boolean (true)10│ └── stripeAccountId: String ("acct_1234...")11├── products/{productId}12│ ├── sellerId: String13│ ├── name: String ("Handmade Leather Wallet")14│ ├── description: String15│ ├── price: Double (49.99)16│ ├── images: List<String> ([url1, url2])17│ ├── category: String ("Accessories")18│ ├── status: String ("active" | "sold" | "paused")19│ └── createdAt: Timestamp20├── orders/{orderId}21│ ├── buyerId: String22│ ├── sellerId: String23│ ├── productId: String24│ ├── productName: String25│ ├── total: Double (49.99)26│ ├── commission: Double (5.00)27│ ├── sellerPayout: Double (44.99)28│ ├── status: String ("placed"|"shipped"|"delivered")29│ └── timestamp: Timestamp30└── orders/{orderId}/messages/{msgId}31 ├── senderId: String32 ├── text: String33 └── timestamp: Timestamp3435Buyer Flow:36├── BrowsePage: GridView (all active products)37│ ├── DropDown (category filter)38│ ├── Slider (price range)39│ └── Product Card → Tap → ProductDetailPage40├── ProductDetailPage: images, details, seller card41│ └── Buy Now → Cloud Function: createMarketplaceCheckout42│ → Launch URL (Stripe Checkout with Connect split)43└── OrdersPage: buyer's orders with status + messaging4445Seller Flow:46├── SellerDashboard (TabBar)47│ ├── Products Tab: CRUD product listings48│ ├── Orders Tab: fulfillment status updates49│ └── Earnings Tab: revenue / commission / payout50└── Connect Stripe: onboardSeller → Stripe Express onboardingCommon mistakes when building a Marketplace with FlutterFlow
Why it's a problem: Using a single Stripe account for all marketplace payments instead of Stripe Connect
How to avoid: Use Stripe Connect with Express accounts for each seller. Stripe handles payout splitting, tax reporting (1099s), and compliance automatically. Set application_fee_amount for your platform commission.
Why it's a problem: Letting sellers edit order financial fields (total, commission, sellerPayout)
How to avoid: Set Firestore rules to block seller writes on financial fields. Only Cloud Functions (triggered by Stripe webhooks) should create and update order financial data.
Why it's a problem: Not validating seller identity before allowing product listings
How to avoid: Require Stripe Connect onboarding (which includes identity verification) before activating a seller's storefront. Set isVerified to true only after Stripe confirms the account is active.
Best practices
- Use Stripe Connect Express accounts for each seller — Stripe handles identity verification and tax compliance
- Set application_fee_amount on each payment to automatically collect your platform commission
- Soft-delete products (set status to paused) instead of hard-deleting to preserve order history references
- Gate seller dashboard access behind a Firestore check for an existing sellers document
- Store order financial calculations (total, commission, payout) via Cloud Functions only — never trust client writes
- Add a review system tied to completed orders so only real buyers can leave seller reviews
- Implement a dispute/refund flow where either party can flag an order for platform review
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
Design a Firestore data model for a multi-seller marketplace with sellers, products, and orders collections. Include Stripe Connect integration for split payments. Write the Cloud Function that creates a Stripe Checkout Session with application_fee_amount and transfer_data.destination for the seller's Stripe account.
Create a product browsing page with a GridView showing product images, names, prices, and seller names. Add a dropdown for category filtering and a price range slider. Each product card should navigate to a detail page on tap. Also create a seller dashboard with tabs for Products, Orders, and Earnings.
Frequently asked questions
What is the difference between a marketplace and a single-store e-commerce app?
A single-store e-commerce app has one seller (the app owner) selling products. A marketplace has multiple independent sellers, each with their own storefront, inventory, and earnings. The platform takes a commission on each sale via Stripe Connect.
How does Stripe Connect split payments between the platform and sellers?
When creating a Checkout Session, set payment_intent_data.application_fee_amount to your commission (e.g., 10% of the price) and transfer_data.destination to the seller's Stripe Connect account ID. Stripe automatically sends the remainder to the seller and keeps your fee in your platform account.
How do I handle product reviews and seller ratings?
Create a reviews subcollection under products with fields: buyerId, rating (1-5), text, and timestamp. Only allow reviews from users who have a completed order for that product (check in Firestore rules or Cloud Function). Calculate the seller's average rating via a Cloud Function that updates the seller document's rating field whenever a new review is submitted.
Can sellers list both physical and digital products?
Yes. Add a productType field (physical or digital) to products. For digital products, include a downloadUrl field and grant access after purchase via a Cloud Function that creates a signed URL. Skip shipping status for digital orders.
How do I handle refunds in a marketplace?
Use Stripe's Refund API in a Cloud Function. When refunding, decide if the platform absorbs the application fee or if it is also refunded. Call stripe.refunds.create with the payment intent ID and optionally reverse_transfer: true to pull funds back from the seller's Connect account.
Can RapidDev help build a production marketplace with dispute resolution and analytics?
Yes. A production marketplace needs dispute resolution workflows, seller verification, fraud detection, analytics dashboards, search with Algolia, and legal compliance for money transmission. RapidDev can architect and build the complete platform.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation