# How to Create a Social Network with Friend Connections in FlutterFlow

- Tool: FlutterFlow
- Difficulty: Beginner
- Time required: 25-30 min
- Compatibility: FlutterFlow Free+
- Last updated: March 2026

## TL;DR

Build a Facebook-style friend connection system where users send, accept, or reject friend requests. Friendships are bidirectional — on acceptance, create friend documents in both users' subcollections using a batch write. Add a People You May Know feature using mutual friend queries and a search page for finding users by name. Display friend lists in a GridView with avatars.

## Building Bidirectional Friend Connections in FlutterFlow

Unlike follow models where relationships are one-way, friend connections are bidirectional — both users must agree. This tutorial builds the full friend system: sending requests, accepting or rejecting, displaying friend lists, discovering new people, and handling unfriending. All friendships are stored symmetrically in both users' subcollections.

## Before you start

- A FlutterFlow project with Firebase authentication enabled
- Firestore database with a users collection containing displayName and photoUrl fields
- Familiarity with FlutterFlow Backend Queries and Action Flows
- Understanding of Firestore subcollections

## Step-by-step guide

### 1. Create the Firestore schema for friend requests and friendships

Create a top-level `friend_requests` collection with fields: fromUserId (String), toUserId (String), status (String: pending/accepted/rejected), timestamp (Timestamp). Then, under the existing users collection, add a `friends` subcollection for each user with fields: friendUserId (String), displayName (String), photoUrl (String), connectedAt (Timestamp). Also add a friendCount integer field on the user document for quick display without querying the subcollection. Register these collections in FlutterFlow's Data section.

**Expected result:** The friend_requests collection and users/{uid}/friends subcollection are created and visible in FlutterFlow's Data panel.

### 2. Build the user search and Add Friend functionality

Create a FindFriends page with a TextField at the top for search input. Below it, add a ListView bound to a Backend Query on the users collection. Use a Search filter on the displayName field with prefix matching (Firestore: where displayName >= searchTerm and displayName < searchTerm + 'z'). Each result shows a CircleImage avatar, displayName Text, and a conditional button: if a pending friend_request exists from the current user to this user, show 'Request Sent' (disabled). If they are already friends, show 'Friends' (disabled). Otherwise, show an 'Add Friend' button. On Add Friend tap, create a friend_requests document with fromUserId as the current user, toUserId as the selected user, status 'pending', and the current timestamp.

**Expected result:** Users can search by name and send friend requests. The button state reflects whether a request is pending or the user is already a friend.

### 3. Create the friend request inbox with accept and reject actions

Create a FriendRequests page or tab showing incoming requests. Add a ListView bound to a Backend Query on the friend_requests collection filtered by toUserId == currentUser.uid AND status == 'pending', ordered by timestamp descending. Each item shows the sender's CircleImage avatar, displayName, and a Row with Accept (green) and Reject (red) buttons. On Accept tap, execute a sequence of actions: (1) Update the friend_request status to 'accepted'. (2) Create a document in users/{currentUser.uid}/friends with friendUserId = fromUserId, the sender's name and photo, and connectedAt = now. (3) Create a matching document in users/{fromUserId}/friends with friendUserId = currentUser.uid. (4) Increment friendCount on both user documents using FieldValue.increment(1). On Reject tap, simply update the friend_request status to 'rejected'.

**Expected result:** Incoming friend requests appear in a list. Accepting creates friend documents in both users' subcollections. Rejecting updates the request status.

### 4. Display the friend list in a GridView with unfriend option

On the user's profile page or a dedicated Friends tab, add a GridView bound to a Backend Query on users/{currentUser.uid}/friends ordered by connectedAt descending. Each grid item shows a CircleImage avatar and displayName Text. Wrap each item in a GestureDetector: on tap, navigate to that friend's profile page passing their userId. Add a long-press action that shows a BottomSheet with an Unfriend button. On Unfriend tap, show a confirmation dialog, then delete the friend document from both users' subcollections and decrement friendCount on both user documents. Add a Text above the GridView showing the total friend count from the user document.

**Expected result:** Friends appear in a grid with avatars and names. Tapping navigates to their profile. Long-pressing offers the unfriend option.

### 5. Build the People You May Know feature with mutual friend logic

On the FindFriends page, add a section above the search results titled 'People You May Know'. To populate this, create a Cloud Function that: (1) reads the current user's friend list, (2) for each friend, reads their friend list, (3) collects users who appear in friends-of-friends but are NOT already the current user's friend and have no pending request, (4) ranks by number of mutual friends, (5) writes the top 10 suggestions to a `friend_suggestions` subcollection on the current user's document. In FlutterFlow, add a horizontal ListView bound to this subcollection. Each item shows the user's avatar, name, a mutual friends count text, and an Add Friend button.

**Expected result:** A horizontal row of suggested friends appears based on mutual connections, each showing the number of shared friends and an Add Friend button.

## Complete code example

File: `FlutterFlow Action Flow — Friend Request System`

```text
// Firestore Schema
// Collection: friend_requests
//   - fromUserId: String
//   - toUserId: String
//   - status: String (pending | accepted | rejected)
//   - timestamp: Timestamp

// Subcollection: users/{uid}/friends
//   - friendUserId: String
//   - displayName: String (denormalized)
//   - photoUrl: String (denormalized)
//   - connectedAt: Timestamp

// User doc additions:
//   - friendCount: Integer (denormalized)

// Action Flow: Send Friend Request
// 1. Check: no existing request between these two users
// 2. Create Document → friend_requests:
//    fromUserId: currentUser.uid
//    toUserId: selectedUser.uid
//    status: 'pending'
//    timestamp: now
// 3. Optional: send notification to toUserId

// Action Flow: Accept Friend Request
// (Use Batch Write for atomicity)
// 1. Update friend_requests/{id}: status → 'accepted'
// 2. Create users/{currentUser.uid}/friends/{docId}:
//    friendUserId: fromUserId
//    displayName: sender.displayName
//    photoUrl: sender.photoUrl
//    connectedAt: now
// 3. Create users/{fromUserId}/friends/{docId}:
//    friendUserId: currentUser.uid
//    displayName: currentUser.displayName
//    photoUrl: currentUser.photoUrl
//    connectedAt: now
// 4. Update users/{currentUser.uid}:
//    friendCount: FieldValue.increment(1)
// 5. Update users/{fromUserId}:
//    friendCount: FieldValue.increment(1)

// Action Flow: Reject Friend Request
// 1. Update friend_requests/{id}: status → 'rejected'

// Action Flow: Unfriend
// (Use Batch Write for atomicity)
// 1. Delete users/{currentUser.uid}/friends
//    where friendUserId == targetUserId
// 2. Delete users/{targetUserId}/friends
//    where friendUserId == currentUser.uid
// 3. Update users/{currentUser.uid}:
//    friendCount: FieldValue.increment(-1)
// 4. Update users/{targetUserId}:
//    friendCount: FieldValue.increment(-1)

// Page: FindFriends
// Column:
//   → Text "People You May Know"
//   → ListView.horizontal (friend_suggestions)
//     → Container: CircleImage + name + mutual count + Add btn
//   → TextField (search by name)
//   → ListView (search results)
//     → Container: CircleImage + name + conditional button

// Page: FriendRequests
// ListView (friend_requests where toUserId==me, status==pending)
//   → Container: CircleImage + name + Accept btn + Reject btn
```

## Common mistakes

- **Creating a friend document in only one user's subcollection instead of both** — Friendships are bidirectional. If you only add user B to user A's friends, then user B's friend list will not show user A. The relationship is asymmetric and broken. Fix: On accept, use a Firestore batch write to create friend documents in BOTH users/{fromUserId}/friends AND users/{toUserId}/friends atomically.
- **Querying the friends subcollection to display friend count on profiles** — Counting subcollection documents requires reading every document, which costs one read per friend. For users with hundreds of friends, this is expensive and slow. Fix: Denormalize a friendCount integer on the user document. Increment on accept, decrement on unfriend. Display this single field instead of counting subcollection docs.
- **Not checking for existing friend requests before sending a new one** — Users can spam multiple friend requests to the same person, filling up their inbox with duplicates and creating a confusing experience. Fix: Before creating a friend_request, query for existing documents where fromUserId and toUserId match (in either direction). If one exists with status pending, show 'Request already sent'.

## Best practices

- Use batch writes when creating or deleting friend documents to ensure both users' data stays in sync
- Denormalize friend displayName and photoUrl on the friend subcollection document to avoid extra reads
- Store friendCount on the user document for quick display without subcollection queries
- Check for existing requests in both directions before allowing a new friend request
- Show different button states based on friendship status: Add Friend, Request Sent, Friends, or Accept/Reject
- Use a Cloud Function to generate friend suggestions based on mutual connections
- Add a notification when a friend request is received so users do not miss it

## Frequently asked questions

### What is the difference between a friend model and a follow model?

A friend model is bidirectional — both users must agree (like Facebook). A follow model is unidirectional — user A can follow user B without B's approval (like Twitter). This tutorial implements the friend model.

### How do I handle the case where user A sends a request to user B, and user B also sends one to user A?

Before creating a new request, check for an existing pending request in the opposite direction. If one exists, automatically accept both by creating the friendship directly instead of creating a duplicate request.

### Can I limit how many friends a user can have?

Yes. Check the friendCount on the user document before allowing new friend requests. If it exceeds your limit, show a message that the user's friend list is full.

### How do I show mutual friends on a user's profile?

Query the visited user's friends subcollection and the current user's friends subcollection, then find the intersection. Display matching users as 'X mutual friends' with their avatars.

### Should I delete rejected friend requests from Firestore?

Keep them with status 'rejected' for a cooldown period (e.g., 30 days) to prevent the sender from immediately resending. After the cooldown, a scheduled Cloud Function can clean up old rejected requests.

### Can RapidDev help build a complete social networking platform?

Yes. RapidDev can implement friend connections, news feeds, messaging, groups, events, notifications, and content moderation into a full-featured social networking app.

---

Source: https://www.rapidevelopers.com/flutterflow-tutorials/how-to-create-a-social-network-with-friend-connections-in-flutterflow
© RapidDev — https://www.rapidevelopers.com/flutterflow-tutorials/how-to-create-a-social-network-with-friend-connections-in-flutterflow
