# How to Create a Platform for Freelance Services in FlutterFlow

- Tool: FlutterFlow
- Difficulty: Beginner
- Time required: 45-60 min
- Compatibility: FlutterFlow Free+ (Cloud Functions and Stripe Connect require Firebase Blaze plan)
- Last updated: March 2026

## TL;DR

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.

## Before you start

- 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

### 1. 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.

### 2. 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.

### 3. 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.

### 4. 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.

### 5. 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 code example

File: `FlutterFlow Freelance Platform Setup`

```text
FIRESTORE DATA MODEL:
  freelancers/{freelancerId}
    userId: Reference (users)
    displayName: String
    title: String (e.g., 'Full-Stack Developer')
    bio: String
    avatarUrl: String
    stripeAccountId: String
    rating: Double
    reviewCount: Int
    completedOrders: Int

  gigs/{gigId}
    freelancerId: Reference (freelancers)
    title: String
    description: String
    category: String (Design | Development | Writing | Marketing | Video | Music)
    priceRange: Map { min: 50.0, max: 500.0 }
    deliveryDays: Int
    portfolioUrls: Array of Strings
    tags: Array of Strings
    rating: Double
    orderCount: Int
    isActive: Boolean

  orders/{orderId}
    clientId: Reference (users)
    freelancerId: Reference (freelancers)
    gigId: Reference (gigs)
    requirements: String
    price: Double
    status: String (pending | inProgress | delivered | revision | completed | cancelled)
    deadline: Timestamp
    stripePaymentIntentId: String
    deliverableUrls: Array of Strings
    revisionCount: Int (max 2)
    createdAt: Timestamp
    completedAt: Timestamp

  orders/{orderId}/messages/{messageId}
    senderId: Reference (users)
    text: String
    timestamp: Timestamp

ORDER LIFECYCLE:
  Client places order → status: pending
  Freelancer accepts → status: inProgress (deadline set)
  Freelancer delivers → status: delivered (files uploaded)
  Client approves → status: completed (payment captured)
  Client requests revision → status: revision (max 2x)
  Auto-approve after 7 days of no response → completed

PAGE: BrowseGigsPage
  Column
    TextField (search)
    ChoiceChips (categories)
    GridView (crossAxisCount: 2)
      Card: portfolio image + title + freelancer row + price + rating

PAGE: OrderDetailPage (adapts by role + status)
  Column
    Status badge (color-coded)
    Text (requirements)
    If delivered: Images (deliverableUrls)
    Action buttons:
      Freelancer + pending: Button "Accept Order"
      Freelancer + inProgress: Button "Deliver Work" + UploadButton
      Client + delivered: Button "Approve" + Button "Request Revision"
    Divider
    Messages ListView (chat bubbles)
    TextField + Send button
```

## Common mistakes

- **Releasing payment to the freelancer immediately when the order is created** — The client has not received any work yet. Immediate payment gives the freelancer no incentive to deliver, and the client has no recourse if work is never completed. Fix: 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.
- **Not limiting the number of revision requests a client can make** — Unlimited revisions let clients endlessly request changes, effectively getting unlimited work for a fixed price and exploiting freelancers. Fix: Set a revisionCount field with a maximum of 2 revisions. After the limit, the client can only approve or escalate to dispute resolution.
- **Using a single shared chat for all communication instead of per-order messaging** — When a client has multiple orders with the same freelancer, messages from different projects mix together, creating confusion about which order a message relates to. Fix: 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

## 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.

---

Source: https://www.rapidevelopers.com/flutterflow-tutorials/how-to-create-a-platform-for-freelance-services-in-flutterflow
© RapidDev — https://www.rapidevelopers.com/flutterflow-tutorials/how-to-create-a-platform-for-freelance-services-in-flutterflow
