Build a freelance services marketplace where freelancers create gig listings with pricing and portfolio samples, and clients browse, order, and communicate through per-order messaging. Stripe Connect handles escrow payments — funds are captured on order but only transferred to the freelancer when the client approves the delivered work. An order lifecycle tracks status from pending through delivery, revision, and completion.
Building a Fiverr-Style Freelance Services Marketplace in FlutterFlow
A freelance platform connects service providers with clients through gig listings, order management, and escrow payments. Unlike product marketplaces, freelance platforms must handle custom requirements per order, a revision cycle, and payment release only after client approval. This tutorial covers the full flow from gig creation to payment payout using FlutterFlow, Firestore, Cloud Functions, and Stripe Connect.
Prerequisites
- A FlutterFlow project with Firestore and Firebase Authentication configured
- A Stripe account with Connect enabled for marketplace payments
- Firebase Blaze plan for Cloud Functions and Storage
- Firebase Storage for deliverable file uploads
Step-by-step guide
Design the Firestore data model for gigs, orders, and messaging
Design the Firestore data model for gigs, orders, and messaging
Create a freelancers collection with: userId (Reference), displayName (String), title (String, e.g., Full-Stack Developer), bio (String), avatarUrl (String), stripeAccountId (String), rating (Double), reviewCount (Int), completedOrders (Int). Create gigs with: freelancerId (Reference), title (String), description (String), category (String: Design/Development/Writing/Marketing/Video/Music), priceRange (Map with min and max Doubles), deliveryDays (Int), portfolioUrls (Array of Strings, sample work images), tags (Array of Strings), rating (Double), orderCount (Int), isActive (Boolean). Create orders with: clientId (Reference), freelancerId (Reference), gigId (Reference), requirements (String, client's brief), price (Double, agreed price), status (String: pending/inProgress/delivered/revision/completed/cancelled/disputed), deadline (Timestamp), stripePaymentIntentId (String), deliverableUrls (Array of Strings), revisionCount (Int, max 2), createdAt (Timestamp), completedAt (Timestamp). Create orders/{id}/messages subcollection for per-order chat.
Expected result: Firestore has a complete freelance marketplace schema with gigs, orders with lifecycle tracking, and per-order messaging.
Build the gig browsing and freelancer profile pages
Build the gig browsing and freelancer profile pages
Create a BrowseGigsPage with a search TextField and category ChoiceChips (All, Design, Development, Writing, Marketing, Video, Music) at the top. Display a GridView of gigs where isActive is true, filtered by selected category. Each card shows: first portfolioUrl image, title (maxLines 2), freelancer avatar + name Row, price range Text (From $X), rating stars + orderCount. Tapping navigates to GigDetailPage showing full description, all portfolio images in a horizontal PageView, delivery time, price details, freelancer bio with link to full FreelancerProfilePage, reviews ListView (from a reviews subcollection), and an Order This Gig button. The FreelancerProfilePage shows all of a freelancer's active gigs, overall stats, and reviews.
Expected result: Clients can browse gigs by category, view detailed gig pages with portfolio samples, and access freelancer profiles with ratings.
Implement order creation with Stripe Connect escrow payment
Implement order creation with Stripe Connect escrow payment
On the Order This Gig button tap, open an OrderFormPage with: the gig title and price displayed, a requirements TextField (multiline, for the client to describe what they need), an optional file attachment FlutterFlowUploadButton for reference materials, and a Confirm Order button. On confirm, call a Cloud Function createFreelanceOrder(gigId, clientId, requirements, price). The function creates a Stripe Payment Intent with capture_method manual (authorization only, not captured yet) and transfer_data pointing to the freelancer's stripeAccountId. It creates the order doc with status pending and the stripePaymentIntentId. The client's card is authorized for the amount but not charged until work is approved. Navigate to the order detail page.
Expected result: The client's payment is authorized (held) but not captured, and the order is created with status pending. The freelancer receives an order notification.
Build the order lifecycle with delivery, revision, and approval
Build the order lifecycle with delivery, revision, and approval
Create an OrderDetailPage showing order status, requirements, messaging, and action buttons that change based on status and user role. Freelancer actions: Accept Order (pending → inProgress, sets deadline), Deliver Work (upload deliverables via FlutterFlowUploadButton, status → delivered). Client actions on delivered status: Approve (triggers payment capture, status → completed) or Request Revision (status → revision, revisionCount incremented, max 2 revisions). On Approve, call a Cloud Function that captures the Stripe Payment Intent and transfers funds minus platform fee to the freelancer. Update the freelancer's completedOrders count and trigger a review prompt. If the client does not respond within 7 days of delivery, a scheduled Cloud Function auto-approves and captures payment.
Expected result: Orders flow through a complete lifecycle from pending to completed, with deliverable uploads, revision requests, and payment release on approval.
Build per-order messaging and the freelancer dashboard
Build per-order messaging and the freelancer dashboard
On the OrderDetailPage, add a messaging section below the order details. Query orders/{orderId}/messages ordered by timestamp. Display as a chat-style ListView with sender avatar, message text, and timestamp. Add a TextField + Send button pinned at the bottom. On send, create a message doc and send a push notification to the other party via Cloud Function. For the freelancer dashboard, create a FreelancerDashboardPage with TabBar: Active Orders, Completed, Earnings. Active Orders tab: ListView of orders where status is pending, inProgress, delivered, or revision. Completed tab: ListView of completed orders with client reviews. Earnings tab: total earnings Text, monthly earnings chart (Custom Widget), pending payouts from Stripe Connect balance, and a link to the Stripe Express dashboard for payout management.
Expected result: Clients and freelancers communicate per order, and freelancers have a full dashboard for managing orders, tracking earnings, and accessing payouts.
Complete working example
1FIRESTORE DATA MODEL:2 freelancers/{freelancerId}3 userId: Reference (users)4 displayName: String5 title: String (e.g., 'Full-Stack Developer')6 bio: String7 avatarUrl: String8 stripeAccountId: String9 rating: Double10 reviewCount: Int11 completedOrders: Int1213 gigs/{gigId}14 freelancerId: Reference (freelancers)15 title: String16 description: String17 category: String (Design | Development | Writing | Marketing | Video | Music)18 priceRange: Map { min: 50.0, max: 500.0 }19 deliveryDays: Int20 portfolioUrls: Array of Strings21 tags: Array of Strings22 rating: Double23 orderCount: Int24 isActive: Boolean2526 orders/{orderId}27 clientId: Reference (users)28 freelancerId: Reference (freelancers)29 gigId: Reference (gigs)30 requirements: String31 price: Double32 status: String (pending | inProgress | delivered | revision | completed | cancelled)33 deadline: Timestamp34 stripePaymentIntentId: String35 deliverableUrls: Array of Strings36 revisionCount: Int (max 2)37 createdAt: Timestamp38 completedAt: Timestamp3940 orders/{orderId}/messages/{messageId}41 senderId: Reference (users)42 text: String43 timestamp: Timestamp4445ORDER LIFECYCLE:46 Client places order → status: pending47 Freelancer accepts → status: inProgress (deadline set)48 Freelancer delivers → status: delivered (files uploaded)49 Client approves → status: completed (payment captured)50 Client requests revision → status: revision (max 2x)51 Auto-approve after 7 days of no response → completed5253PAGE: BrowseGigsPage54 Column55 TextField (search)56 ChoiceChips (categories)57 GridView (crossAxisCount: 2)58 Card: portfolio image + title + freelancer row + price + rating5960PAGE: OrderDetailPage (adapts by role + status)61 Column62 Status badge (color-coded)63 Text (requirements)64 If delivered: Images (deliverableUrls)65 Action buttons:66 Freelancer + pending: Button "Accept Order"67 Freelancer + inProgress: Button "Deliver Work" + UploadButton68 Client + delivered: Button "Approve" + Button "Request Revision"69 Divider70 Messages ListView (chat bubbles)71 TextField + Send buttonCommon mistakes when creating a Platform for Freelance Services in FlutterFlow
Why it's a problem: Releasing payment to the freelancer immediately when the order is created
How to avoid: Use Stripe's manual capture (escrow) pattern: authorize the payment on order creation but capture and transfer only when the client approves the delivered work.
Why it's a problem: Not limiting the number of revision requests a client can make
How to avoid: Set a revisionCount field with a maximum of 2 revisions. After the limit, the client can only approve or escalate to dispute resolution.
Why it's a problem: Using a single shared chat for all communication instead of per-order messaging
How to avoid: Create a messages subcollection under each order document. Each order has its own isolated chat thread tied to that specific project.
Best practices
- Use Stripe Connect with manual capture for escrow — authorize on order, capture on approval
- Auto-approve orders after 7 days of client inactivity to protect freelancers from unresponsive clients
- Limit revisions to 2 per order to prevent exploitation while allowing reasonable adjustments
- Create per-order messaging subcollections to keep conversations organized by project
- Prompt clients to leave a review after order completion to build freelancer reputation
- Store portfolio samples as URLs in gig documents for quick browsing without heavy queries
- Send push notifications on order status changes so neither party misses important updates
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I want to build a freelance services marketplace in FlutterFlow like Fiverr. Show me the Firestore data model for gigs and orders, Stripe Connect escrow payment flow, order lifecycle with delivery and revision, and per-order messaging.
Create a gig detail page with a horizontal image carousel at the top showing portfolio samples. Below, show the gig title, description, delivery time, and price range. Add a freelancer section with avatar, name, rating, and completed orders count. Add an Order This Gig button at the bottom.
Frequently asked questions
How does the escrow payment protect both parties?
The client's payment is authorized (held on their card) when the order is placed but not transferred to the freelancer until they approve the delivered work. This protects clients from non-delivery and guarantees freelancers that funds are available.
What happens if the client never responds to a delivery?
A scheduled Cloud Function checks for orders in delivered status older than 7 days. If the client has not responded, it auto-approves the order, captures the payment, and transfers funds to the freelancer.
How do I handle disputes between clients and freelancers?
Add a Dispute button that sets order status to disputed and creates a dispute document with both parties' statements. An admin reviews the dispute and either releases payment to the freelancer or refunds the client.
Can freelancers offer different pricing tiers for the same gig?
Yes. Add a tiers array to the gig document with entries like Basic ($50, 3 days, 1 revision), Standard ($100, 5 days, 2 revisions), Premium ($200, 7 days, unlimited revisions). The client selects a tier when placing an order.
How do I calculate and display the platform fee?
Set the platform fee percentage (e.g., 15%) in a Firestore config document. On order creation, the Cloud Function calculates applicationFeeAmount as price times the fee percentage. Display the breakdown to both parties: client pays full price, freelancer receives price minus platform fee.
What if I need a full-featured freelance marketplace with dispute resolution and analytics?
RapidDev has built freelance and service marketplace platforms in FlutterFlow with Stripe Connect escrow, automated dispute resolution, freelancer verification, portfolio management, and platform analytics dashboards.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation