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.
Related Template
Try this production-ready starter kit to build your project faster.
Shop All Products
Wireless Headphones
Leather Backpack
Smart Watch
Sunglasses
E-Commerce Starter
Build your online store the smart way
Ready to Build?
Get started with our production-ready starter kits and ship your project faster.
Browse Starter Kits