Back to Blog
ยท7 min

Multi-Vendor Marketplace Template: Build an E-Commerce Platform

Multi-vendor marketplaces like Etsy, Airbnb, and DoorDash are among the most valuable e-commerce platforms. Building a marketplace requires vendor onboarding, commission management, dispute resolution, payment splitting, and review systems โ€” all significantly more complex than a single-vendor store.

A multi-vendor marketplace template provides the complete infrastructure so you can launch your platform and onboard vendors immediately.

Core Marketplace Features

A production-ready marketplace template includes:

  • Vendor registration and onboarding
  • Product listing management per vendor
  • Shopping cart across multiple vendors
  • Commission calculation and Stripe Connect payouts
  • Order management with split payments
  • Review and rating system
  • Dispute resolution center
  • Analytics dashboard per vendor

The RentEasy template includes marketplace functionality with Stripe Connect integration.

Vendor Onboarding

// app/api/vendors/onboard/route.ts
import { NextResponse } from 'next/server'
import Stripe from 'stripe'
import { auth } from '@/lib/auth'
import { prisma } from '@/lib/prisma'

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!)

export async function POST() {
  const session = await auth()
  if (!session?.user) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })

  const existingVendor = await prisma.vendor.findUnique({
    where: { userId: session.user.id },
  })

  if (existingVendor?.stripeAccountId) {
    const link = await stripe.accountLinks.create({
      account: existingVendor.stripeAccountId,
      refresh_url: `${process.env.NEXT_PUBLIC_APP_URL}/vendor/onboarding`,
      return_url: `${process.env.NEXT_PUBLIC_APP_URL}/vendor/dashboard`,
      type: 'account_onboarding',
    })
    return NextResponse.json({ url: link.url })
  }

  const account = await stripe.accounts.create({
    type: 'express',
    country: 'US',
    email: session.user.email!,
    capabilities: { transfers: { requested: true }, card_payments: { requested: true } },
  })

  await prisma.vendor.upsert({
    where: { userId: session.user.id },
    update: { stripeAccountId: account.id },
    create: { userId: session.user.id, stripeAccountId: account.id },
  })

  const link = await stripe.accountLinks.create({
    account: account.id,
    refresh_url: `${process.env.NEXT_PUBLIC_APP_URL}/vendor/onboarding`,
    return_url: `${process.env.NEXT_PUBLIC_APP_URL}/vendor/dashboard`,
    type: 'account_onboarding',
  })

  return NextResponse.json({ url: link.url })
}

Product Listing Component

'use client'

import { useState } from 'react'
import { Star, ShoppingCart, Heart } from 'lucide-react'

interface Product {
  id: string
  title: string
  price: number
  image: string
  vendor: string
  rating: number
  reviews: number
}

export function MarketplaceGrid({ products }: { products: Product[] }) {
  const [wishlist, setWishlist] = useState<Set<string>>(new Set())

  const toggleWishlist = (id: string) => {
    const next = new Set(wishlist)
    if (next.has(id)) next.delete(id)
    else next.add(id)
    setWishlist(next)
  }

  return (
    <div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
      {products.map(product => (
        <div key={product.id} className="group rounded-xl border bg-white overflow-hidden">
          <div className="relative aspect-square overflow-hidden bg-gray-100">
            <img
              src={product.image}
              alt={product.title}
              className="h-full w-full object-cover group-hover:scale-105 transition-transform"
            />
            <button
              onClick={() => toggleWishlist(product.id)}
              className="absolute right-2 top-2 rounded-full bg-white p-2 shadow"
            >
              <Heart className={`h-4 w-4 ${wishlist.has(product.id) ? 'fill-red-500 text-red-500' : 'text-gray-400'}`} />
            </button>
          </div>
          <div className="p-4">
            <p className="text-xs text-gray-500">{product.vendor}</p>
            <h3 className="mt-1 font-semibold">{product.title}</h3>
            <div className="mt-1 flex items-center gap-1 text-sm">
              <Star className="h-3.5 w-3.5 fill-yellow-400 text-yellow-400" />
              <span className="font-medium">{product.rating}</span>
              <span className="text-gray-400">({product.reviews})</span>
            </div>
            <div className="mt-3 flex items-center justify-between">
              <span className="text-lg font-bold">${product.price}</span>
              <button className="rounded-lg bg-brand-600 px-4 py-1.5 text-sm font-semibold text-white">
                Add to Cart
              </button>
            </div>
          </div>
        </div>
      ))}
    </div>
  )
}

Launch your marketplace platform with the RentEasy multi-vendor template.

Browse all 200+ templates and starter kits.

Ready to Build?

Get started with our production-ready starter kits and ship your project faster.

Browse Starter Kits