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

How to Build a Social Networking App with FlutterFlow

Build a social networking app using Firestore collections for users, posts, and subcollections for likes, comments, and following relationships. Display a home feed by querying posts where the authorId is in the current user's followingIds array. Implement follow and unfollow with atomic counter updates, and add like and comment interactions using subcollection documents with denormalized counts on the parent post.

What you'll learn

  • How to model users, posts, follows, likes, and comments in Firestore
  • How to build a home feed filtered by the user's following list
  • How to implement follow and unfollow with atomic counter updates
  • How to add like and comment interactions on posts
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner9 min read30-40 minFlutterFlow Free+March 2026RapidDev Engineering Team
TL;DR

Build a social networking app using Firestore collections for users, posts, and subcollections for likes, comments, and following relationships. Display a home feed by querying posts where the authorId is in the current user's followingIds array. Implement follow and unfollow with atomic counter updates, and add like and comment interactions using subcollection documents with denormalized counts on the parent post.

Full social network with follows, feed, likes, and comments

This tutorial builds a social networking app from scratch in FlutterFlow. Users create profiles, follow other users, publish text and image posts, and interact through likes and comments. The Firestore data model uses subcollections for scalable relationships, denormalized counts for performant display, and the whereIn query for feed generation. The result is a functional Instagram-style social app built entirely in the visual builder.

Prerequisites

  • A FlutterFlow project with Firebase/Firestore connected
  • Firebase Authentication enabled with user sign-in working
  • Basic understanding of Backend Queries, Conditional Visibility, and Action Flows
  • Familiarity with Firestore subcollections and document references

Step-by-step guide

1

Set up the Firestore data model for users, posts, and relationships

Create a users collection with fields: displayName (String), avatarUrl (String), bio (String), followerCount (Integer, default 0), followingCount (Integer, default 0), and followingIds (List of Strings, default empty). Create a posts collection with: authorId (String), content (String), imageUrl (String, optional), likeCount (Integer, default 0), commentCount (Integer, default 0), timestamp (Timestamp). Under each post, create two subcollections: likes with fields userId (String) and timestamp (Timestamp), and comments with fields userId (String), text (String), and timestamp (Timestamp). Under each user, create a following subcollection with a document per followed user containing followedUserId (String) and followedAt (Timestamp). The followingIds array on the user doc is a denormalized list of user IDs they follow, used for feed queries.

Expected result: Firestore has users, posts, posts/{id}/likes, posts/{id}/comments, and users/{uid}/following collections ready.

2

Build the home feed page with post cards

Create a HomePage with a ListView bound to a Backend Query on the posts collection, filtered with whereIn on authorId using the current user's followingIds array, ordered by timestamp descending, limit 20 with infinite scroll ON. Each item uses a PostCard Component containing: a Row with CircleImage (author avatar queried from users doc) and Text (author displayName), the post content Text, an optional Image (Conditional Visibility: imageUrl is not empty), and an action Row with IconButton for like (heart icon), Text for likeCount, IconButton for comment, and Text for commentCount. Add a FloatingActionButton for creating new posts. If followingIds is empty, show an empty state with a message suggesting users to find people to follow.

Expected result: The home feed shows posts only from users the current user follows, each with author info, content, image, and interaction counts.

3

Implement follow and unfollow with atomic counter updates

Create a UserProfilePage that receives a userId parameter. Display the user's avatar, displayName, bio, followerCount, and followingCount in a header section. Add a Follow/Unfollow button with Conditional Visibility: show Follow when the current user's followingIds array does not contain this userId, show Unfollow when it does. Follow button On Tap Action Flow: create a document in users/{currentUser.uid}/following with followedUserId, then Update Document on the current user to add the userId to followingIds using FieldValue.arrayUnion and increment followingCount by 1, then Update Document on the target user to increment followerCount by 1. Unfollow reverses this: delete the following doc, FieldValue.arrayRemove on followingIds, decrement both counts with FieldValue.increment(-1). Below the header, add a ListView of this user's posts filtered by authorId.

Expected result: Tapping Follow adds the user to your following list and increments both follower/following counts. Unfollow reverses everything.

4

Add post creation with text and optional image upload

Create a CreatePostPage or a BottomSheet triggered by the FAB on the home feed. Include a multiline TextField for post content (maxLines 5, hint text 'What is on your mind?') and a FlutterFlowUploadButton for optional image attachment. The Upload button stores the image in Firebase Storage under posts/{userId}/{timestamp}.jpg and returns the download URL. Add a Post button at the bottom. On Tap Action Flow: validate that content is not empty, then Create Document in posts with authorId set to the current user's UID, content from the TextField, imageUrl from the upload result (or empty string if no image), likeCount 0, commentCount 0, and timestamp as server timestamp. After creation, navigate back to the home feed. The real-time feed query picks up the new post automatically.

Expected result: Users can write a text post with an optional image and publish it. The post appears in their followers' feeds immediately.

5

Implement like and comment interactions on posts

On the PostCard Component, wire the heart IconButton's On Tap Action Flow: first query posts/{postId}/likes where userId equals currentUser.uid. If a like doc exists, delete it and decrement the post's likeCount by 1 (unlike). If no like doc exists, create one with userId and timestamp, and increment likeCount by 1 (like). Toggle the heart icon between outlined (unliked) and filled red (liked) using Conditional Styling based on the like query result. For comments, tapping the comment IconButton navigates to a CommentsPage showing a ListView of posts/{postId}/comments ordered by timestamp ascending. At the bottom, a TextField with a Send IconButton creates a new comment doc and increments the post's commentCount by 1.

Expected result: Users can like and unlike posts with the heart icon toggling state. Comments appear in a dedicated view with a text input for adding new ones.

Complete working example

Social Network Architecture
1Firestore Data Model:
2 users/{uid}
3 displayName: String
4 avatarUrl: String
5 bio: String
6 followerCount: Integer (142)
7 followingCount: Integer (89)
8 followingIds: List<String> ["uid_a", "uid_b", ...]
9 following/{docId} (subcollection)
10 followedUserId: String
11 followedAt: Timestamp
12 posts/{postId}
13 authorId: String (user UID)
14 content: String ("Just launched my app!")
15 imageUrl: String (optional)
16 likeCount: Integer (23)
17 commentCount: Integer (5)
18 timestamp: Timestamp
19 likes/{likeId} (subcollection)
20 userId: String
21 timestamp: Timestamp
22 comments/{commentId} (subcollection)
23 userId: String
24 text: String
25 timestamp: Timestamp
26
27HomePage (Feed):
28 ListView (posts where authorId IN followingIds, orderBy timestamp DESC)
29 PostCard Component
30 Row CircleImage (avatar) + Text (displayName) + Text (timeAgo)
31 Text (content)
32 Image (imageUrl) [Cond. Vis: imageUrl not empty]
33 Row (actions)
34 IconButton (heart: outlined/filled) + Text (likeCount)
35 IconButton (comment) + Text (commentCount)
36 IconButton (share)
37 FAB Navigate CreatePostPage
38
39UserProfilePage:
40 Column (header)
41 CircleImage (avatar, 80x80)
42 Text (displayName)
43 Text (bio)
44 Row Text(posts) + Text(followerCount) + Text(followingCount)
45 Button (Follow / Unfollow, conditional)
46 ListView (user's posts, authorId == this userId)
47
48Action Flows:
49 Follow: Create following doc arrayUnion followingIds increment counts
50 Unfollow: Delete following doc arrayRemove followingIds decrement counts
51 Like: Create likes subcollection doc increment likeCount
52 Unlike: Delete likes doc decrement likeCount
53 Comment: Create comments doc increment commentCount

Common mistakes when building a Social Networking App with FlutterFlow

Why it's a problem: Firestore whereIn limited to 10 values — users following 100+ people cannot load their feed in one query

How to avoid: Batch the followingIds array into groups of 10 and run parallel queries, merging and sorting results client-side. For larger scale, use a Cloud Function to pre-compute each user's feed using a fan-out-on-write pattern.

Why it's a problem: Not denormalizing followerCount and followingCount on the user document

How to avoid: Store followerCount and followingCount as Integer fields on the user doc. Increment and decrement them atomically with FieldValue.increment(1) or FieldValue.increment(-1) on every follow or unfollow action.

Why it's a problem: Checking like status by querying the likes subcollection on every feed scroll

How to avoid: For the initial version, query like status only when the user taps into a post detail. For optimization, maintain a likedPostIds array on the user doc (same arrayUnion/arrayRemove pattern) and check locally.

Best practices

  • Denormalize likeCount, commentCount, followerCount, and followingCount on parent documents for instant display
  • Use FieldValue.increment for all counter updates to avoid race conditions
  • Limit feed queries to 20 posts with infinite scroll to control read costs
  • Store followingIds as an array on the user doc for fast feed filtering with whereIn
  • Use Conditional Styling to toggle like icon state rather than re-querying on every render
  • Add Firestore composite indexes for posts queries combining authorId with timestamp ordering
  • Move follow/unfollow logic to Cloud Functions for atomic transaction safety in production

Still stuck?

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

ChatGPT Prompt

Design a Firestore data model for a social networking app with users, posts, likes, comments, and follow relationships. Include denormalized counts and explain the whereIn feed query pattern with its limitations.

FlutterFlow Prompt

Create a social feed page with a ListView of post cards. Each card shows an avatar, username, post text, optional image, and a row with like and comment buttons showing counts. Add a floating action button to create new posts.

Frequently asked questions

How do I handle users who follow more than 10 people for the feed query?

Firestore whereIn supports only 10 values. Split the followingIds array into chunks of 10, run parallel Backend Queries for each chunk, and merge results in a Custom Function sorted by timestamp. For apps with heavy follow counts, use a Cloud Function fan-out-on-write pattern that copies each post to followers' feed subcollections.

How do I show a 'time ago' label like '5 min ago' on posts?

Create a Custom Function that calculates the difference between now and the post timestamp. Return 'Just now' for under one minute, 'Xm' for under an hour, 'Xh' for under a day, and a formatted date for older posts. Bind this function result to a Text widget on the PostCard.

Can I add image uploads to posts?

Yes. Use FlutterFlowUploadButton on the create post form. It uploads to Firebase Storage and returns a download URL. Store this URL in the post's imageUrl field. On the PostCard, use Conditional Visibility to show the Image widget only when imageUrl is not empty.

How do I prevent users from liking a post multiple times?

Before creating a like document, query the likes subcollection where userId equals the current user. If a document exists, the user already liked the post. Toggle to unlike (delete the doc and decrement likeCount) instead of creating a duplicate.

Should I use real-time queries for the feed?

For the home feed, a single-time query with pull-to-refresh is usually sufficient and cheaper. Use real-time queries (Single Time Query OFF) for the comments list and like count on individual post detail pages where instant updates matter most.

Can RapidDev help build a production social network?

Yes. A production social app needs content moderation, push notification pipelines, abuse reporting, algorithmic feed ranking, media processing, and scalable Cloud Functions. RapidDev can design the full architecture beyond what the visual builder handles alone.

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.