Skip to main content
RapidDev - Software Development Agency
flutterflow-tutorials

How to Build a Content Approval Workflow in FlutterFlow

Build a multi-stage content approval workflow using Firestore status fields (draft, submitted, inReview, approved, published, rejected). Authors submit content, reviewers approve or reject with comments, and admins override when needed. Track every status change in a workflow_events subcollection. Use Conditional Visibility and role checks to enforce who can perform each action. Email notifications fire on every status transition via Cloud Functions.

What you'll learn

  • How to model a multi-stage approval workflow with Firestore status fields
  • How to enforce role-based actions so only reviewers can approve or reject
  • How to log a complete workflow history with timestamps and comments
  • How to send email notifications on each status transition via Cloud Functions
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner8 min read25-35 minFlutterFlow Pro+ (Cloud Functions for notifications)March 2026RapidDev Engineering Team
TL;DR

Build a multi-stage content approval workflow using Firestore status fields (draft, submitted, inReview, approved, published, rejected). Authors submit content, reviewers approve or reject with comments, and admins override when needed. Track every status change in a workflow_events subcollection. Use Conditional Visibility and role checks to enforce who can perform each action. Email notifications fire on every status transition via Cloud Functions.

Building an Editorial Approval Pipeline in FlutterFlow

Content-heavy apps need quality gates before publishing. This tutorial builds a full editorial workflow where authors draft and submit, reviewers approve or reject with feedback, and every transition is logged. Role-based controls ensure only authorized users can move content through each stage.

Prerequisites

  • FlutterFlow project with Firebase authentication configured
  • Firestore collections for content and users
  • Users collection with a role field (author, reviewer, admin)
  • Basic understanding of Conditional Visibility in FlutterFlow

Step-by-step guide

1

Create the Firestore schema for content and workflow events

In Firestore, create a content collection with fields: title (String), body (String), authorId (String), workflowStatus (String, default 'draft'), reviewerId (String, optional), reviewComment (String, optional), createdAt (Timestamp), updatedAt (Timestamp). Then add a subcollection workflow_events under each content document with fields: action (String), userId (String), comment (String), timestamp (Timestamp). The status field drives the entire workflow: draft, submitted, inReview, approved, published, or rejected.

Expected result: Firestore has a content collection with status tracking and a workflow_events subcollection for audit history.

2

Build the author submission view with status badges

Create a page called MyContent. Add a ListView bound to a Backend Query on the content collection filtered by authorId equals current user. Each list item shows: title Text, a Container styled as a status badge (green for published, yellow for inReview, red for rejected, grey for draft). Use Conditional Visibility on a Submit button so it only appears when workflowStatus equals 'draft'. The Submit button runs an Action Flow: Update Document to set workflowStatus to 'submitted' and updatedAt to now, then creates a workflow_events doc with action 'submitted'.

Expected result: Authors see their content list with color-coded status badges and can submit draft items for review.

3

Build the reviewer queue with approve and reject actions

Create a ReviewQueue page visible only to users with role 'reviewer' or 'admin'. Add a ListView querying content where workflowStatus equals 'submitted' or 'inReview', ordered by updatedAt ascending. Each item shows the title, author name, and submission date. Add two buttons: Approve and Reject. Approve runs an Action Flow that updates workflowStatus to 'approved', sets reviewerId, and creates a workflow_events doc. Reject opens a dialog with a TextField for reviewer comments, then updates status to 'rejected' with the comment stored on both the content doc and the workflow_events entry.

Expected result: Reviewers see a queue of submitted content and can approve or reject each item with optional comments.

4

Display the workflow history timeline

On the content detail page, add a section below the main content showing the workflow history. Query the workflow_events subcollection ordered by timestamp descending. Display each event in a Column: a Row with the user display name and a formatted timestamp, below it the action text (styled bold) and any comment. Use a vertical line or Container border on the left side to create a timeline visual effect. This gives authors and reviewers full visibility into every status transition and who performed it.

Expected result: A chronological timeline shows every workflow action with the actor name, timestamp, and any reviewer comments.

5

Lock editing for content not in draft status

On the content edit page, wrap all editable fields (title TextField, body TextField) with Conditional Visibility set to show only when workflowStatus equals 'draft'. When status is anything else, show read-only Text widgets instead. Add a Request Return to Draft button visible only when status is 'rejected', which sets the status back to 'draft' and logs a workflow event. This prevents authors from editing content that is actively being reviewed, which would cause reviewers to see different content than what was submitted.

Expected result: Content fields are locked for editing unless the item is in draft status, preventing mid-review modifications.

6

Add Cloud Function notifications on status changes

Deploy a Cloud Function triggered by Firestore onUpdate on the content collection. When workflowStatus changes, the function determines the recipient: if status changed to 'submitted', email the reviewer team; if changed to 'approved' or 'rejected', email the author. Include the content title, new status, and any reviewer comment in the email body. Use a mail-sending service like SendGrid or Firebase Extensions for email delivery. This keeps all stakeholders informed without requiring them to check the app constantly.

cloud_function_status_notification.js
1// Cloud Function: onContentStatusChange
2const functions = require('firebase-functions');
3const admin = require('firebase-admin');
4admin.initializeApp();
5
6exports.onContentStatusChange = functions.firestore
7 .document('content/{contentId}')
8 .onUpdate(async (change, context) => {
9 const before = change.before.data();
10 const after = change.after.data();
11 if (before.workflowStatus === after.workflowStatus) return;
12
13 const contentTitle = after.title;
14 const newStatus = after.workflowStatus;
15 const comment = after.reviewComment || '';
16
17 // Determine recipient based on new status
18 let recipientId;
19 if (newStatus === 'submitted') {
20 // Notify reviewers (query users with role 'reviewer')
21 const reviewers = await admin.firestore()
22 .collection('users')
23 .where('role', '==', 'reviewer').get();
24 // Send to each reviewer
25 } else {
26 recipientId = after.authorId;
27 }
28 // Send email via SendGrid or Firebase Extension
29 });

Expected result: Email notifications are sent automatically when content moves between workflow stages.

Complete working example

FlutterFlow Content Approval Workflow
1FIRESTORE SCHEMA:
2 content (collection):
3 title: String
4 body: String
5 authorId: String
6 workflowStatus: String (draft|submitted|inReview|approved|published|rejected)
7 reviewerId: String (optional)
8 reviewComment: String (optional)
9 createdAt: Timestamp
10 updatedAt: Timestamp
11 content/{id}/workflow_events (subcollection):
12 action: String
13 userId: String
14 comment: String
15 timestamp: Timestamp
16
17PAGE: MyContent (Author View)
18 ListView Backend Query: content where authorId == currentUser
19 Container (status badge: color by workflowStatus)
20 Text (title)
21 Button "Submit" Conditional Visibility: status == 'draft'
22 Action: Update Document workflowStatus = 'submitted'
23 Action: Create workflow_events doc
24
25PAGE: ReviewQueue (Reviewer View)
26 Conditional Access: currentUser.role == 'reviewer' OR 'admin'
27 ListView Backend Query: content where status IN ['submitted','inReview']
28 Text (title + author + date)
29 Button "Approve" Update status to 'approved' + log event
30 Button "Reject" Show Dialog with comment TextField
31 Update status to 'rejected' + store comment + log event
32
33PAGE: ContentDetail
34 Content display (title, body, status badge)
35 Workflow Timeline section:
36 ListView workflow_events orderBy timestamp desc
37 Row: userName + formatted timestamp
38 Text: action (bold) + comment
39
40EDIT MODE:
41 Conditional Visibility: fields editable only when status == 'draft'
42 Button "Return to Draft" visible when status == 'rejected'
43
44CLOUD FUNCTION:
45 onUpdate content if workflowStatus changed email notification

Common mistakes when building a Content Approval Workflow in FlutterFlow

Why it's a problem: Allowing authors to edit content that is already in review

How to avoid: Lock editing when workflowStatus is anything other than 'draft'. Authors must request a return to draft status before making changes.

Why it's a problem: Only hiding UI buttons without Firestore Security Rules enforcement

How to avoid: Add Firestore Security Rules that check the user's role field before allowing status field updates. Only reviewers and admins can set status to approved or published.

Why it's a problem: Not logging workflow events on every status transition

How to avoid: Create a workflow_events subcollection document on every status change, recording the action, userId, comment, and timestamp.

Why it's a problem: Sending notifications synchronously in the Action Flow

How to avoid: Use a Cloud Function triggered by Firestore onUpdate to send notifications asynchronously. The status update completes immediately and the notification fires in the background.

Best practices

  • Lock content editing when status is not draft to prevent mid-review modifications
  • Enforce status transitions in Firestore Security Rules, not just the UI
  • Log every workflow event in a subcollection for a complete audit trail
  • Color-code status badges so users can scan content state at a glance
  • Send notifications via Cloud Functions so status updates are never blocked by email delivery
  • Include reviewer comments on rejection so authors know exactly what to fix
  • Add a Return to Draft action for rejected content so authors can revise and resubmit

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

Design a content approval workflow for a FlutterFlow app. I need Firestore schema for content with workflowStatus (draft/submitted/inReview/approved/published/rejected), a workflow_events subcollection for audit logs, role-based access for authors and reviewers, and Cloud Functions for email notifications on status changes.

FlutterFlow Prompt

Create a page called ReviewQueue with a ListView showing content documents where workflowStatus is 'submitted'. Each item has the title, author name, and two buttons: Approve and Reject. Approve updates the status to approved. Reject opens a dialog with a comment field then updates status to rejected.

Frequently asked questions

Can I add more than two reviewer levels?

Yes. Add intermediate statuses like inReview1 and inReview2. Each level queries content at its specific status, and approval advances it to the next level. This creates a multi-tier approval chain.

How do I prevent the same reviewer from approving their own content?

In the Approve action, add a condition: if content.authorId equals currentUser.uid, show a SnackBar saying you cannot review your own content. Also enforce this in Firestore Security Rules.

Can rejected content be resubmitted?

Yes. Add a Return to Draft button visible only when status is rejected. This sets the status back to draft so the author can edit and resubmit for another review cycle.

How do I track how long content stays in each stage?

The workflow_events subcollection records timestamps for each transition. Calculate duration by subtracting consecutive event timestamps. Display average review time on an admin dashboard.

Can I add automatic approval for certain content types?

Yes. In the Cloud Function triggered on status change to submitted, check the content type or author trust level. If criteria are met, automatically update the status to approved without manual review.

Can RapidDev help build complex approval workflows?

Yes. RapidDev can build multi-tier approval systems with custom business rules, automated routing, SLA tracking, and integration with external review tools.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.