# How to Set Up FlutterFlow with a Content Recommendation Algorithm

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

## TL;DR

Build a content recommendation engine by tracking user interactions (views, likes, saves, shares) in a Firestore user_interactions collection. A scheduled Cloud Function analyzes each user's interaction history, identifies preferred categories and content patterns, and writes personalized recommendations to a users/{uid}/recommendations subcollection. Display recommendations in a 'Recommended for You' horizontal ScrollView on the home page. Start with simple category-based filtering using arrayContainsAny matching the user's liked categories, then graduate to collaborative filtering with a Cloud Function for higher accuracy.

## Building a Content Recommendation Engine in FlutterFlow

Content recommendations keep users engaged by surfacing relevant content based on their behavior. This tutorial builds a recommendation system starting with simple category-based filtering and progressing to a Cloud Function pipeline that pre-computes personalized recommendations. Everything is stored in Firestore and displayed with the FlutterFlow visual builder.

## Before you start

- A FlutterFlow project with Firestore and Firebase Authentication configured
- A content collection with at least 20 documents with category and tags fields
- Cloud Functions enabled for the recommendation pipeline
- Basic familiarity with FlutterFlow Backend Queries and App State

## Step-by-step guide

### 1. Set up user interaction tracking in Firestore

Create a user_interactions collection with fields: userId (String), contentId (String), type (String: 'view', 'like', 'save', 'share'), timestamp (Timestamp), contentCategory (String, denormalized for fast queries). Add interaction logging to your app: on content page load, create a 'view' interaction. On like button tap, create a 'like' interaction. On save/bookmark tap, create a 'save' interaction. On share action, create a 'share' interaction. Also update the user document with a likedCategories array field that tracks unique categories the user has interacted with (append on like, deduplicate).

**Expected result:** Every user interaction (view, like, save, share) is logged in Firestore with category information.

### 2. Implement simple category-based recommendations

As a quick starting point before the Cloud Function pipeline, create a Backend Query on the content collection using arrayContainsAny with the current user's likedCategories array. Order by a popularity or recency field. Exclude content the user has already viewed by maintaining a viewedContentIds array in App State (populated on app load from recent user_interactions where type == 'view'). Display results in a 'Recommended for You' horizontal ListView on the home page. Each item is a ContentCard Component showing: thumbnail Image, title Text, category Badge, and a 'Recommended' label.

**Expected result:** Users see content recommendations based on their liked categories, with already-viewed content filtered out.

### 3. Build the Cloud Function recommendation pipeline

Create a scheduled Cloud Function generateRecommendations that runs daily. For each active user: 1) Query their user_interactions from the last 30 days. 2) Calculate a category preference score: likes=3 points, saves=2, shares=2, views=1 per interaction type. 3) Rank categories by score. 4) For the top 3 categories, query content the user has not yet viewed, ordered by popularity. 5) Score each content item: category match score + freshness bonus (newer = higher) + popularity factor. 6) Write the top 20 recommendations to users/{uid}/recommendations subcollection with: contentId, score, reason (e.g., 'Because you liked [category]'). Clear old recommendations before writing new ones.

```
// Cloud Function: generateRecommendations (scheduled daily)
const admin = require('firebase-admin');
const db = admin.firestore();

exports.generateRecommendations = async () => {
  const thirtyDaysAgo = new Date();
  thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);

  const usersSnap = await db.collection('users').get();
  for (const userDoc of usersSnap.docs) {
    const userId = userDoc.id;
    const interactions = await db.collection('user_interactions')
      .where('userId', '==', userId)
      .where('timestamp', '>=', thirtyDaysAgo)
      .get();

    const scores = {};
    const weights = { like: 3, save: 2, share: 2, view: 1 };
    const viewedIds = new Set();

    interactions.docs.forEach(doc => {
      const d = doc.data();
      const cat = d.contentCategory;
      scores[cat] = (scores[cat] || 0) + (weights[d.type] || 1);
      if (d.type === 'view') viewedIds.add(d.contentId);
    });

    const topCats = Object.entries(scores)
      .sort((a, b) => b[1] - a[1])
      .slice(0, 3)
      .map(e => e[0]);

    const content = await db.collection('content')
      .where('category', 'in', topCats)
      .orderBy('popularity', 'desc')
      .limit(50)
      .get();

    const recs = content.docs
      .filter(d => !viewedIds.has(d.id))
      .slice(0, 20)
      .map(d => ({
        contentId: d.id,
        score: scores[d.data().category] || 0,
        reason: `Because you liked ${d.data().category}`,
      }));

    // Write recommendations
    const recsRef = db.collection(`users/${userId}/recommendations`);
    const batch = db.batch();
    const oldRecs = await recsRef.get();
    oldRecs.docs.forEach(d => batch.delete(d.ref));
    recs.forEach(r => batch.set(recsRef.doc(), r));
    await batch.commit();
  }
};
```

**Expected result:** A daily Cloud Function computes personalized recommendations and stores them in each user's subcollection.

### 4. Display pre-computed recommendations on the home page

On your HomePage, add a 'Recommended for You' section. Use a horizontal ListView with a Backend Query on users/{currentUser.uid}/recommendations ordered by score descending. Each item queries the content document by contentId (using a second Backend Query or a Document Reference) to get the full content details. Display each as a ContentCard: thumbnail Image, title Text, category Badge Container, and a reason Text below (e.g., 'Because you liked Technology'). Add a 'See All' TextButton that navigates to a full recommendations page with a vertical ListView. If the recommendations subcollection is empty (new user), fall back to a 'Trending' query showing the most popular content.

**Expected result:** The home page shows a personalized recommendation carousel with content the user is likely to enjoy.

### 5. Add user preference controls and feedback loop

Create a PreferencesPage where users can explicitly set content preferences. Display all content categories as ChoiceChips. Pre-select categories from the user's likedCategories array. Let users add or remove categories. Save changes to the user document. Also add feedback to recommendations: on each recommended item, add 'Not Interested' and 'Show More Like This' options. 'Not Interested' creates a dismissed_recommendations document. 'Show More Like This' creates a 'like' interaction boosting that category. The Cloud Function reads dismissed_recommendations to exclude those items from future results.

**Expected result:** Users can tune their preferences and provide feedback on recommendations to improve future suggestions.

## Complete code example

File: `FlutterFlow Recommendation Setup`

```text
FIRESTORE DATA MODEL:
  content/{contentId}
    title: String
    body: String
    thumbnailUrl: String
    category: String
    tags: [String]
    popularity: Integer
    createdAt: Timestamp

  user_interactions/{docId}
    userId: String
    contentId: String
    type: "view" | "like" | "save" | "share"
    timestamp: Timestamp
    contentCategory: String (denormalized)

  users/{uid}
    likedCategories: [String]
    └── recommendations/{docId}
          contentId: String
          score: Number
          reason: String
    └── dismissed_recommendations/{docId}
          contentId: String

INTERACTION LOGGING:
  On Content Page Load:
    → Create user_interactions doc (type: 'view')
  On Like Button:
    → Create user_interactions doc (type: 'like')
    → Update user likedCategories array (add category)
  On Save/Share:
    → Create user_interactions doc (type: 'save'/'share')

SIMPLE CATEGORY FILTER (immediate):
  content
    .where('category', 'in', currentUser.likedCategories[:3])
    .orderBy('popularity', 'desc')
    .limit(20)

CLOUD FUNCTION PIPELINE (daily):
  For each user:
    1. Query 30-day interactions
    2. Score categories (like=3, save=2, share=2, view=1)
    3. Get top 3 categories
    4. Query unseen content in those categories
    5. Score and rank content
    6. Write top 20 to recommendations subcollection

HOME PAGE:
  Column
    ├── Text ("Recommended for You")
    ├── ListView.horizontal
    │     Backend Query: recommendations, order by score desc
    │     └── ContentCard Component
    │           ├── Image (thumbnail)
    │           ├── Text (title)
    │           ├── Container (category badge)
    │           └── Text (reason, small italic)
    ├── Text ("Trending")
    └── ListView.horizontal
          Backend Query: content, order by popularity desc
```

## Common mistakes

- **Running the recommendation algorithm on the client side** — The client would need to read thousands of user_interactions and content documents to compute recommendations. This is slow, expensive, and exposes business logic to the user. Fix: Pre-compute recommendations in a scheduled Cloud Function and store results in a user subcollection. The client reads only 20 pre-computed recommendation documents.
- **Not excluding already-viewed content from recommendations** — Showing content the user has already seen feels like the recommendations are broken. It wastes valuable recommendation slots on content that cannot convert. Fix: Track viewedContentIds from user_interactions and filter them out in both the Cloud Function pipeline and the simple category-based fallback query.
- **Only using view counts as the recommendation signal** — Views are weak signals. A user might view content they dislike. Likes, saves, and shares are much stronger indicators of genuine interest. Fix: Weight interaction types differently: likes and saves are 2-3x more valuable than views. Use the weighted scoring system in the Cloud Function.

## Best practices

- Pre-compute recommendations in a scheduled Cloud Function, not on the client
- Weight interaction types: likes/saves > shares > views for better signal quality
- Denormalize content category on interaction documents for efficient Cloud Function queries
- Exclude already-viewed content from recommendation results
- Fall back to trending/popular content for new users with no interaction history
- Combine implicit signals (views, likes) with explicit preferences for best results
- Show the reason for each recommendation to build user trust and engagement

## Frequently asked questions

### How many user interactions do I need before recommendations are useful?

Start showing category-based recommendations after 5-10 interactions. The Cloud Function pipeline becomes meaningful after 20-30 interactions per user. For brand new users, show trending or popular content as a cold-start fallback.

### Can I use collaborative filtering instead of content-based filtering?

Yes. Collaborative filtering finds users with similar interaction patterns and recommends what those similar users liked. Implement this in the Cloud Function by computing user-user similarity scores based on shared likes, then recommending content liked by similar users that the target user has not seen.

### How do I handle the cold-start problem for new content?

New content has no interaction data. Boost new content by adding a freshness factor to the scoring algorithm: content less than 7 days old gets a bonus score. Also, show new content in a dedicated 'New' section separate from personalized recommendations.

### Will the daily Cloud Function be expensive at scale?

For up to 10,000 users, a daily Cloud Function runs within free-tier limits. For larger scale, process users in batches, only recompute for users active in the last 7 days, and use Firestore batch writes to minimize operations.

### Can I add real-time recommendations that update as the user browses?

Yes. In addition to the daily pre-computed recommendations, add a lightweight real-time layer: after each interaction, immediately query content in the same category as the just-interacted content and show it in a 'More Like This' section.

### Can RapidDev help build an advanced recommendation engine?

Yes. RapidDev can implement a full recommendation system including collaborative filtering, content-based filtering, hybrid approaches, A/B testing of algorithms, real-time updates, and integration with ML platforms for deep learning models.

---

Source: https://www.rapidevelopers.com/flutterflow-tutorials/how-to-set-up-flutterflow-with-a-content-recommendation-algorithm
© RapidDev — https://www.rapidevelopers.com/flutterflow-tutorials/how-to-set-up-flutterflow-with-a-content-recommendation-algorithm
