Build a collaborative project management tool with Kanban boards, team member assignment, and activity feeds. Create Firestore collections for projects, tasks, and activity logs. Use a horizontal ScrollView for Kanban columns, DropDown for assignee selection, and Cloud Functions to notify team members when tasks change status or are assigned.
Building a Team Project Management Tool in FlutterFlow
Project management apps help teams track tasks, assign responsibilities, and stay aligned. This tutorial builds a collaborative tool with Kanban columns, member management, task assignment, and an activity feed — all scoped so only project members see their team's data.
Prerequisites
- A FlutterFlow project with Firebase authentication enabled
- Firestore database set up with read/write rules
- Basic understanding of Firestore collections and document references
- Familiarity with FlutterFlow Action Flows and Backend Queries
Step-by-step guide
Create the Firestore schema for projects, tasks, and activity
Create the Firestore schema for projects, tasks, and activity
In your Firebase Console, create a top-level `projects` collection with fields: name (String), description (String), ownerId (String), memberIds (List of Strings), status (String: active/archived), createdAt (Timestamp). Then create a subcollection `tasks` under each project with fields: title (String), description (String), status (String: todo/inProgress/review/done), assigneeId (String), priority (String: low/medium/high), dueDate (Timestamp), tags (List of Strings). Finally add an `activity` subcollection with fields: userId (String), action (String), details (String), timestamp (Timestamp). In FlutterFlow, go to the Data section and add these as Firestore collections so you can bind them to queries.
Expected result: Three collections appear in FlutterFlow's Data panel: projects, tasks (subcollection), and activity (subcollection).
Build the project list page with team member avatars
Build the project list page with team member avatars
Add a new page called ProjectList. Drag a ListView widget and bind it to a Backend Query on the `projects` collection filtered by arrayContains on memberIds matching the current user's UID. For each list item, add a Container with a Row containing the project name as a Text widget, a secondary Text showing the member count, and a Row of CircleImage widgets displaying the first 3 member avatars (query user docs by memberIds). Add a FloatingActionButton that opens a dialog to create a new project — set ownerId to the current user and add their UID to the memberIds array.
Expected result: The page displays only projects where the current user is a member, each showing its name and team member avatars.
Create the Kanban board with horizontal status columns
Create the Kanban board with horizontal status columns
Add a ProjectBoard page that receives a projectId parameter. Add a horizontal ScrollView at the top level. Inside it, place four Column widgets side by side, each representing a status: To Do, In Progress, Review, and Done. Give each column a fixed width of 280px and a light background color. Inside each column, add a ListView bound to a Backend Query on the project's tasks subcollection filtered by status matching that column's value, ordered by priority. Each task card is a Container with the task title, assignee CircleImage, priority color-coded dot, and due date. Add a tap action on each card to navigate to a TaskDetail page.
Expected result: Four scrollable columns display tasks grouped by status, each card showing the task title, assignee avatar, and priority indicator.
Add task creation and assignee selection with DropDown
Add task creation and assignee selection with DropDown
Add an Add Task button at the bottom of the To Do column. On tap, open a BottomSheet with a form: TextField for title, TextField for description, a DropDown bound to the project's memberIds (display user names by querying user docs) for assignee selection, a ChoiceChips widget for priority (Low/Medium/High), and a DatePicker for due date. On submit, create a new document in the tasks subcollection with status set to 'todo' and the selected field values. Also create an activity log entry: '{userName} created task {taskTitle}'.
Expected result: Tapping Add Task opens a form where the user fills in details, selects an assignee from team members, and the task appears in the To Do column.
Implement task status changes and the activity feed
Implement task status changes and the activity feed
On the TaskDetail page, add a DropDown at the top with values: todo, inProgress, review, done. Bind it to the task's current status. On change, update the task document's status field and create a new activity log entry: '{userName} moved {taskTitle} to {newStatus}'. Below the task details, add a ListView bound to the project's activity subcollection ordered by timestamp descending. Each activity item shows a CircleImage of the user, the action text, and a relative timestamp. This gives the team a full audit trail of all project changes.
Expected result: Changing a task's status updates it in Firestore and immediately logs the change in the activity feed visible to all project members.
Invite team members and set up Firestore security rules
Invite team members and set up Firestore security rules
On the ProjectBoard page, add a Settings icon in the AppBar. On tap, navigate to a ProjectSettings page showing current members in a ListView with their name and role. Add an Invite button that opens a dialog with a TextField for email. On submit, query the users collection for that email, then add their UID to the project's memberIds array using arrayUnion. For Firestore Security Rules, add: allow read, write if request.auth.uid in resource.data.memberIds — this ensures only project members can access project data. For task subcollections, inherit the parent project's member check.
Expected result: Team members can be invited by email, their UID is added to the project, and Firestore rules prevent non-members from accessing any project data.
Complete working example
1// Firestore Schema2// Collection: projects3// - name: String4// - description: String5// - ownerId: String (current user UID)6// - memberIds: List<String>7// - status: String (active | archived)8// - createdAt: Timestamp910// Subcollection: projects/{projectId}/tasks11// - title: String12// - description: String13// - status: String (todo | inProgress | review | done)14// - assigneeId: String (UID from memberIds)15// - priority: String (low | medium | high)16// - dueDate: Timestamp17// - tags: List<String>1819// Subcollection: projects/{projectId}/activity20// - userId: String21// - action: String22// - details: String23// - timestamp: Timestamp2425// Page: ProjectBoard26// Layout: Scaffold → horizontal ScrollView27// → Column (To Do, width: 280)28// → Text heading "To Do"29// → ListView (query: tasks where status == 'todo')30// → Container (task card)31// → Row: Text(title) + CircleImage(assignee)32// → Row: Container(priority dot) + Text(dueDate)33// → Button "+ Add Task" → BottomSheet34// → Column (In Progress, width: 280)35// → same pattern, status == 'inProgress'36// → Column (Review, width: 280)37// → same pattern, status == 'review'38// → Column (Done, width: 280)39// → same pattern, status == 'done'4041// Action Flow: Change Task Status42// 1. DropDown onChange → Update Document (task.status = newValue)43// 2. Create Document in activity subcollection:44// { userId: currentUser, action: 'status_change',45// details: '{task.title} moved to {newValue}',46// timestamp: now }47// 3. Cloud Function: onWrite to tasks48// → if assigneeId changed, send notification to new assignee49// → if status changed, send notification to task creatorCommon mistakes
Why it's a problem: Giving all team members full CRUD access to all projects without scoping
How to avoid: Add Firestore rules: allow read, write: if request.auth.uid in resource.data.memberIds. This ensures only listed project members can access the data.
Why it's a problem: Using Page State instead of Firestore for task status changes
How to avoid: Always write status changes directly to Firestore. Use real-time listeners (set Single Time Query to OFF) so all connected team members see updates instantly.
Why it's a problem: Not creating a composite Firestore index for tasks filtered by status
How to avoid: Check the Firebase Console logs for missing index errors and create the required composite index on status + priority for the tasks subcollection.
Why it's a problem: Querying all projects instead of filtering by memberIds
How to avoid: Always filter the projects query with arrayContains: currentUserUid on the memberIds field to show only projects the user belongs to.
Best practices
- Use arrayContains on memberIds to scope all project queries to the current user
- Set Single Time Query to OFF on task ListViews for real-time collaboration updates
- Color-code priority indicators: green for low, yellow for medium, red for high
- Denormalize the last activity summary on the project document for quick display in the project list
- Log every significant action to the activity subcollection to maintain a full audit trail
- Limit Kanban columns to a fixed width so they scroll horizontally without breaking the layout
- Use Cloud Functions to send push notifications on task assignment and status changes
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I'm building a collaborative project management tool in FlutterFlow with Firestore. I need a Kanban board with To Do, In Progress, Review, and Done columns, task assignment to team members via a DropDown, an activity feed logging all changes, and Firestore Security Rules that restrict access to project members only. Show me the Firestore schema and FlutterFlow page layout.
Create a project management page with four horizontal Kanban columns (To Do, In Progress, Review, Done). Each column shows tasks from a Firestore subcollection filtered by status. Include task cards with title, assignee avatar, and priority. Add a form to create new tasks with an assignee DropDown.
Frequently asked questions
How many team members can a single project support?
Firestore array fields have a practical limit of about 40,000 bytes. For the memberIds array, this supports hundreds of UIDs comfortably. For very large teams, consider a separate members subcollection instead.
Can I add drag-and-drop to move tasks between Kanban columns?
FlutterFlow does not support native drag-and-drop between widgets. You can use a Custom Widget with Flutter's LongPressDraggable and DragTarget, or use a DropDown on each task card to change its status column.
How do I prevent two users from editing the same task simultaneously?
Use Firestore transactions when updating task fields. This ensures that if two users change the same task at the same time, one write will fail gracefully and can be retried.
Can I archive completed projects instead of deleting them?
Yes. Add an 'archived' status to the project document. Filter your project list query to show only status == 'active'. Archived projects remain accessible for reference but are hidden from the default view.
How do I add due date reminders for tasks?
Create a scheduled Cloud Function that runs daily, queries tasks with dueDate approaching within 24 hours, and sends push notifications to the assigned team members.
Can RapidDev help build a full project management platform?
Yes. RapidDev can implement advanced features like Gantt charts, time tracking, resource allocation, sprint planning, and integrations with tools like Slack and Jira.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation