Build a customer support live chat with a floating action button that opens a chat Bottom Sheet for users and a separate agent dashboard for support staff. Store support_chats with status tracking (waiting, active, resolved) and a messages subcollection for real-time messaging. Users send messages via a TextField pinned at the bottom. Agents see a queue of waiting chats, claim one to begin responding, and use canned response quick-reply buttons for common answers. A Cloud Function auto-assigns chats to available agents when no agent claims within 30 seconds.
Building Customer Support Live Chat in FlutterFlow
Live chat connects app users with human support agents in real-time. Unlike peer-to-peer messaging, live chat requires queue management, agent assignment, and resolution tracking. This tutorial builds both the user-facing chat widget and the agent-side dashboard with claim system, canned responses, and chat resolution workflow.
Prerequisites
- A FlutterFlow project with Firestore and Firebase Authentication configured
- A users collection with a role field to distinguish agents from regular users
- Basic familiarity with FlutterFlow Bottom Sheets, ListViews, and real-time Backend Queries
Step-by-step guide
Set up the Firestore data model for support chats and messages
Set up the Firestore data model for support chats and messages
Create a support_chats collection with fields: userId (String), agentId (String, nullable), status (String: 'waiting', 'active', 'resolved'), subject (String), createdAt (Timestamp), resolvedAt (Timestamp, nullable), lastMessageAt (Timestamp). Create a support_chats/{chatId}/messages subcollection with: senderId (String), text (String), timestamp (Timestamp), isAgent (Boolean). Create a canned_responses collection with: text (String), category (String: 'greeting', 'troubleshooting', 'closing'), shortcut (String), order (Integer). This model separates the chat lifecycle (status) from the messages for clean queue management.
Expected result: Firestore has support_chats with messages subcollection and canned_responses ready for live chat.
Build the user-facing chat widget with FloatingActionButton trigger
Build the user-facing chat widget with FloatingActionButton trigger
On your main app pages, add a FloatingActionButton with a chat bubble Icon in the bottom-right corner. Show a Badge with unread message count using a Backend Query counting messages where isAgent == true and timestamp > lastReadTimestamp. On FAB tap, check if the user has an existing support_chats document with status 'waiting' or 'active'. If yes, open the existing chat. If no, create a new support_chats document with status 'waiting' and open it. The chat opens as a Bottom Sheet with a Column: header Row (subject Text + close IconButton), messages ListView (real-time Backend Query on messages subcollection ordered by timestamp ascending), and an input Row at the bottom with TextField and send IconButton.
Expected result: Users tap a floating chat button to start or resume a support conversation in a Bottom Sheet.
Create the agent dashboard with chat queue and claim system
Create the agent dashboard with chat queue and claim system
Create an AgentDashboardPage (Conditional Visibility: user role == 'agent'). Add two tabs: Queue and My Chats. The Queue tab shows a ListView with Backend Query on support_chats where status == 'waiting', ordered by createdAt ascending. Each row shows: user avatar, subject, waiting time (calculated from createdAt), and an 'Accept' Button. On Accept tap: update the chat document agentId to currentUser.uid and status to 'active'. This removes it from other agents' queues. The My Chats tab shows a ListView filtered by agentId == currentUser.uid AND status == 'active'. Tap a chat to open the agent-side chat view.
Expected result: Agents see a queue of waiting chats and can claim them. Claimed chats move to the agent's active list.
Implement the agent chat view with canned responses
Implement the agent chat view with canned responses
Create an AgentChatPage with Route Parameter chatId. Display the same message ListView as the user view but with agent-specific additions. Above the input Row, add a horizontal ScrollView of canned response Containers from a Backend Query on canned_responses ordered by order. Each Container shows the shortcut text. On tap, insert the canned response text into the TextField. Below the canned responses, add the standard input Row: TextField and send IconButton. On send, create a message document with isAgent: true. Add a 'Resolve' Button in the header that updates the chat status to 'resolved', sets resolvedAt to now, and sends a closing message.
Expected result: Agents can reply using canned responses or custom messages and resolve chats when complete.
Add auto-assignment and real-time status updates
Add auto-assignment and real-time status updates
Create a Cloud Function autoAssignChat triggered on support_chats document creation (status == 'waiting'). After a 30-second delay (Cloud Tasks or scheduled), check if the chat still has status 'waiting' (no agent claimed it). If so, query users where role == 'agent' and find the one with the fewest active chats (least busy), then assign agentId and set status to 'active'. On the user side, show status indicators: 'Waiting for agent...' Text with a loading animation when status == 'waiting', and 'Connected to [agentName]' when status == 'active'. Use a real-time listener on the support_chats document to update the status display instantly.
Expected result: Unclaimed chats are auto-assigned to the least busy agent, and users see real-time status updates.
Complete working example
1FIRESTORE DATA MODEL:2 support_chats/{chatId}3 userId: String4 agentId: String (nullable)5 status: "waiting" | "active" | "resolved"6 subject: String7 createdAt: Timestamp8 resolvedAt: Timestamp (nullable)9 lastMessageAt: Timestamp10 └── messages/{messageId}11 senderId: String12 text: String13 timestamp: Timestamp14 isAgent: Boolean1516 canned_responses/{docId}17 text: String18 category: "greeting" | "troubleshooting" | "closing"19 shortcut: String20 order: Integer2122USER SIDE:23 FloatingActionButton (chat icon, bottom-right)24 Badge: unread agent message count25 On Tap:26 → Check existing chat (waiting/active)27 → If none: Create support_chats doc (status: waiting)28 → Open ChatSheet Bottom Sheet2930 ChatSheet:31 Column32 ├── Row (subject + status indicator + close)33 ├── Text ("Waiting..." if status == waiting)34 ├── ListView (messages, real-time, ordered timestamp)35 │ isAgent true → left aligned, grey bg36 │ isAgent false → right aligned, primary bg37 └── Row (TextField + send IconButton)3839AGENT SIDE:40 AgentDashboardPage (role == 'agent' only)41 TabBar: Queue | My Chats42 Queue Tab:43 ListView (support_chats, status == waiting, oldest first)44 Row: avatar + subject + wait time + Accept Button45 Accept: set agentId, status = 'active'46 My Chats Tab:47 ListView (support_chats, agentId == me, status == active)4849 AgentChatPage:50 Column51 ├── Row (user info + Resolve Button)52 ├── ListView (messages, real-time)53 ├── ScrollView.horizontal (canned responses)54 └── Row (TextField + send IconButton)Common mistakes
Why it's a problem: No agent claim system causing multiple agents to respond to the same chat
How to avoid: Implement a claim system: the Accept button atomically sets agentId and changes status to 'active', immediately removing the chat from other agents' queues.
Why it's a problem: Using a Single Time Query instead of real-time for the message list
How to avoid: Disable Single Time Query on the messages Backend Query so it uses a real-time Firestore listener. New messages appear instantly.
Why it's a problem: Not showing the chat status to the user while waiting for an agent
How to avoid: Show a clear status indicator: 'Waiting for an agent...' with a loading animation when status is waiting, and 'Connected to [name]' when an agent accepts.
Best practices
- Use a claim system where agents explicitly accept chats to prevent duplicate responses
- Enable real-time Firestore listeners for instant message delivery on both sides
- Show clear status indicators (waiting, connected, resolved) to keep users informed
- Pre-populate canned responses for common questions to speed up agent response time
- Auto-assign unclaimed chats after a timeout to prevent users waiting indefinitely
- Track resolution time (resolvedAt - createdAt) for agent performance metrics
- Add a satisfaction rating prompt after chat resolution for quality monitoring
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I want to build a customer support live chat in FlutterFlow. Show me the Firestore data model for support chats with queue management, a user-facing chat bottom sheet triggered by a floating action button, an agent dashboard with queue and claim system, canned responses, and auto-assignment for unclaimed chats.
Create a chat bottom sheet with a header showing chat status, a scrollable message list in the center, a row of quick reply buttons above the input, and a text field with send button pinned at the bottom.
Frequently asked questions
Can I add a chatbot that handles common questions before connecting to an agent?
Yes. Add an initial automated flow where the bot asks the user's question category and checks against a FAQ database. If no match, create the support_chats document with status 'waiting' to route to a human agent.
How do I handle multiple simultaneous chats per agent?
On the My Chats tab, the agent sees all their active chats in a list. They can switch between chats by tapping each one. Set a maximum concurrent chat limit (e.g., 5) in the auto-assignment Cloud Function to prevent agent overload.
Can I add file and image sharing in the chat?
Yes. Add a type field to messages (text, image, file). Include an attachment IconButton next to the TextField. Use FlutterFlowUploadButton to upload to Firebase Storage and save the download URL in the message document.
How do I send push notifications when a new message arrives?
Create a Cloud Function triggered on message creation in the messages subcollection. Look up the recipient (agent or user) FCM token and send a push notification with the message preview.
Can I track agent response time and performance?
Yes. Calculate first response time (first agent message timestamp minus chat createdAt), average response time between messages, and resolution time (resolvedAt minus createdAt). Display these metrics on an admin analytics page.
Can RapidDev help build a complete customer support system?
Yes. RapidDev can implement a full support system including live chat, chatbot automation, ticket management, agent analytics, customer satisfaction surveys, and integration with tools like Zendesk or Intercom.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation