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

How to Create a News Feed Algorithm in FlutterFlow

Create a feed ranking algorithm that scores each post using a weighted formula combining recency decay, engagement metrics, and author affinity. A scheduled Cloud Function computes scores and writes ranked results to each user's personal ranked_feed subcollection. The FlutterFlow client simply reads the pre-computed feed for instant display. Store algorithm weights in a Firestore config document so you can tune ranking without redeploying code.

What you'll learn

  • How to design a feed scoring formula with recency, engagement, and affinity weights
  • How to pre-compute ranked feeds using a scheduled Cloud Function
  • How to store tunable algorithm weights in Firestore for live adjustments
  • How to display a For You feed with toggle to Latest chronological view
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner8 min read25-35 minFlutterFlow Free+March 2026RapidDev Engineering Team
TL;DR

Create a feed ranking algorithm that scores each post using a weighted formula combining recency decay, engagement metrics, and author affinity. A scheduled Cloud Function computes scores and writes ranked results to each user's personal ranked_feed subcollection. The FlutterFlow client simply reads the pre-computed feed for instant display. Store algorithm weights in a Firestore config document so you can tune ranking without redeploying code.

Building a Smart Feed Ranking Algorithm in FlutterFlow

A chronological feed quickly becomes unusable as content grows. This tutorial builds the ranking algorithm behind a For You feed. Posts are scored by recency, engagement, and how much the user interacts with each author. A Cloud Function pre-computes the ranked feed per user, so the client reads a simple sorted list with zero computation.

Prerequisites

  • A FlutterFlow project with Firestore and authentication configured
  • A posts collection with fields for likes, comments, shares, and authorId
  • Cloud Functions environment configured
  • At least 10 sample posts from multiple authors for testing

Step-by-step guide

1

Design the Firestore data model for ranked feeds and algorithm config

Create a ranked_feed subcollection under each user document: users/{uid}/ranked_feed/{postId} with fields: postId (String), score (Double), title (String), authorName (String), thumbnailUrl (String), engagementCount (Integer), createdAt (Timestamp). Also create an algorithm_config document at the root level with fields: recency_weight (Double, default 0.4), engagement_weight (Double, default 0.35), affinity_weight (Double, default 0.25), decay_half_life_hours (Integer, default 24). This config document lets you tune the algorithm without changing code.

Expected result: Firestore has a ranked_feed subcollection per user and a tunable algorithm_config document.

2

Build the scoring Cloud Function with weighted formula

Create a Cloud Function that runs on a schedule (every 15 minutes). For each active user, it fetches all posts from the last 7 days and scores each one. The formula: score = (recency_weight * decay_function) + (engagement_weight * normalized_engagement) + (affinity_weight * author_interaction_score). The decay function uses exponential decay: 1 / (1 + age_hours / decay_half_life_hours). Normalized engagement = (likes + comments*2 + shares*3) / max_engagement_in_batch. Author interaction score = count of user's likes and comments on that author's previous posts / total_interactions. Apply a diversity penalty of -0.1 if the previous post in the ranked list is from the same author.

rankFeed.js
1// Cloud Function: rankFeed
2const functions = require('firebase-functions');
3const admin = require('firebase-admin');
4
5exports.rankFeed = functions.pubsub
6 .schedule('every 15 minutes').onRun(async () => {
7 const db = admin.firestore();
8 const config = (await db.doc('algorithm_config/default').get()).data();
9 const { recency_weight, engagement_weight,
10 affinity_weight, decay_half_life_hours } = config;
11 const now = Date.now();
12 const weekAgo = new Date(now - 7*24*60*60*1000);
13 const posts = await db.collection('posts')
14 .where('createdAt', '>=', weekAgo).get();
15 const maxEng = Math.max(...posts.docs.map(p => {
16 const d = p.data();
17 return d.likes + d.comments*2 + (d.shares||0)*3;
18 }), 1);
19 const users = await db.collection('users')
20 .where('lastActive', '>=', weekAgo).get();
21 for (const user of users.docs) {
22 const uid = user.id;
23 const interactions = await db
24 .collection('interactions')
25 .where('userId', '==', uid).get();
26 const authorScores = {};
27 let totalInt = Math.max(interactions.size, 1);
28 interactions.forEach(i => {
29 const a = i.data().authorId;
30 authorScores[a] = (authorScores[a]||0) + 1;
31 });
32 const scored = posts.docs.map(p => {
33 const d = p.data();
34 const ageH = (now - d.createdAt.toMillis())
35 / 3600000;
36 const recency = 1 / (1 + ageH / decay_half_life_hours);
37 const eng = (d.likes + d.comments*2
38 + (d.shares||0)*3) / maxEng;
39 const affinity = (authorScores[d.authorId]||0)
40 / totalInt;
41 return {
42 postId: p.id, title: d.title,
43 authorName: d.authorName,
44 thumbnailUrl: d.thumbnailUrl || '',
45 engagementCount: d.likes + d.comments,
46 createdAt: d.createdAt,
47 score: recency_weight * recency
48 + engagement_weight * eng
49 + affinity_weight * affinity
50 };
51 }).sort((a,b) => b.score - a.score);
52 // Diversity penalty
53 for (let i = 1; i < scored.length; i++) {
54 if (scored[i].authorName === scored[i-1].authorName)
55 scored[i].score -= 0.1;
56 }
57 scored.sort((a,b) => b.score - a.score);
58 const batch = db.batch();
59 const feedRef = db.collection(`users/${uid}/ranked_feed`);
60 const old = await feedRef.get();
61 old.forEach(d => batch.delete(d.ref));
62 scored.slice(0, 50).forEach(s => {
63 batch.set(feedRef.doc(s.postId), s);
64 });
65 await batch.commit();
66 }
67 });

Expected result: Cloud Function runs every 15 minutes and writes the top 50 scored posts to each active user's ranked_feed subcollection.

3

Create an admin page to tune algorithm weights in real time

Build an AlgorithmConfigPage accessible to admin users. Add three Slider widgets labeled Recency Weight, Engagement Weight, and Affinity Weight, each ranging from 0.0 to 1.0. Bind their initial values to a Backend Query on algorithm_config/default. Add a TextField for decay_half_life_hours. Include a Save button that updates the algorithm_config document with the new values. Add a note Text widget reminding that changes take effect on the next Cloud Function run (within 15 minutes). This lets you tune ranking live without code changes.

Expected result: Admins can adjust ranking weights via sliders and see changes reflected in the feed within 15 minutes.

4

Build the For You feed page with ranked posts

Create a FeedPage with ChoiceChips at the top: For You and Latest. For the For You tab, add a ListView with a Backend Query on users/{currentUser.uid}/ranked_feed ordered by score descending. For the Latest tab, query the posts collection ordered by createdAt descending. Each list item is a PostCard Container with: thumbnail Image, title Text, author name Text, engagement count with icons, and relative timestamp. Tapping a card navigates to the full post detail page with the postId as a route parameter.

Expected result: Users see a ranked For You feed by default with the option to toggle to a chronological Latest feed.

5

Track user interactions to improve affinity scoring

Create an interactions collection with fields: userId, postId, authorId, type (String: 'like', 'comment', 'share'), timestamp. When a user likes, comments, or shares a post, create an interaction document via an Action Flow. These interactions feed the affinity score in the ranking algorithm. The more a user interacts with a specific author's content, the higher that author's posts rank in their feed. The Cloud Function reads these interactions to calculate author_interaction_score per user.

Expected result: User interactions are tracked in Firestore and used by the ranking algorithm to personalize feed ordering by author affinity.

Complete working example

FlutterFlow News Feed Algorithm Setup
1FIRESTORE DATA MODEL:
2 posts/{postId}
3 title: String
4 authorId: String
5 authorName: String
6 thumbnailUrl: String
7 likes: Integer
8 comments: Integer
9 shares: Integer
10 createdAt: Timestamp
11
12 users/{uid}/ranked_feed/{postId}
13 postId: String
14 score: Double
15 title: String
16 authorName: String
17 thumbnailUrl: String
18 engagementCount: Integer
19 createdAt: Timestamp
20
21 interactions/{interactionId}
22 userId: String
23 postId: String
24 authorId: String
25 type: 'like' | 'comment' | 'share'
26 timestamp: Timestamp
27
28 algorithm_config/default
29 recency_weight: 0.4
30 engagement_weight: 0.35
31 affinity_weight: 0.25
32 decay_half_life_hours: 24
33
34SCORING FORMULA:
35 score = (recency_weight * decay) + (engagement_weight * norm_eng)
36 + (affinity_weight * author_affinity)
37 decay = 1 / (1 + age_hours / decay_half_life_hours)
38 norm_eng = (likes + comments*2 + shares*3) / max_eng
39 author_affinity = user_interactions_with_author / total_interactions
40 diversity_penalty = -0.1 if same author as previous ranked post
41
42PAGE: FeedPage
43 WIDGET TREE:
44 Column
45 ChoiceChips (For You | Latest)
46 Expanded
47 ListView
48 For You: Backend Query ranked_feed, order by score desc
49 Latest: Backend Query posts, order by createdAt desc
50 PostCard Component
51
52 PostCard:
53 Container (padding, border radius)
54 Row
55 Image (thumbnailUrl, 80x80)
56 Column
57 Text (title, bold, maxLines: 2)
58 Text (authorName, grey)
59 Row
60 Icon(heart) + Text(engagementCount)
61 Text (relative timestamp)

Common mistakes when creating a News Feed Algorithm in FlutterFlow

Why it's a problem: Recalculating feed ranking on every user page load

How to avoid: Pre-compute ranked feeds via a scheduled Cloud Function (every 15 minutes) and store results. The client reads the pre-computed list instantly.

Why it's a problem: Hardcoding algorithm weights in the Cloud Function

How to avoid: Store weights in a Firestore algorithm_config document. The Cloud Function reads them at runtime. Admins adjust weights via a UI with immediate effect.

Why it's a problem: Not applying a diversity penalty for consecutive posts by the same author

How to avoid: Apply a diversity penalty (subtract 0.1 from score) when consecutive posts in the ranked list share the same author, then re-sort.

Best practices

  • Pre-compute ranked feeds on a schedule rather than calculating on every page load
  • Store algorithm weights in Firestore for live tuning without code redeployment
  • Apply diversity penalties to prevent any single author from dominating the feed
  • Normalize engagement scores relative to the batch maximum for fair comparison
  • Use exponential decay for recency so older posts gracefully lose ranking
  • Track user interactions (likes, comments, shares) to build author affinity data
  • Limit ranked feed to top 50 posts per user to control Firestore storage costs
  • Provide a chronological Latest toggle so users can bypass the algorithm

Still stuck?

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

ChatGPT Prompt

I want to build a news feed ranking algorithm in FlutterFlow. Show me the scoring formula combining recency decay, engagement metrics, and author affinity. Include a Cloud Function that pre-computes ranked feeds per user, a Firestore config for tunable weights, and the FlutterFlow page layout with For You and Latest toggle.

FlutterFlow Prompt

Create a feed page with choice chips at the top labeled For You and Latest. Below add a list view showing post cards. Each card has a thumbnail image on the left and title text with engagement count on the right.

Frequently asked questions

How often should the ranking Cloud Function run?

Every 15 minutes is a good balance between freshness and cost. For high-volume apps with rapidly changing content, you can reduce to every 5 minutes. For lower volume, every hour works fine.

Can I A/B test different algorithm configurations?

Yes. Create multiple algorithm_config documents (variant_a, variant_b). Assign users to variants randomly. The Cloud Function reads the user's assigned config and applies those weights. Track engagement metrics per variant.

What happens for new users with no interaction history?

When a user has zero interactions, the affinity component is zero for all authors. The feed ranks purely on recency and engagement, effectively showing popular recent content. As the user interacts, personalization kicks in gradually.

How do I prevent the algorithm from creating filter bubbles?

Inject a small percentage of random or diverse posts (from unfollowed authors, different categories) into the ranked feed. This exploration component exposes users to new content beyond their interaction patterns.

Will pre-computing feeds for thousands of users be expensive?

Only compute for active users (those who logged in within the past 7 days). For 1,000 active users with 100 posts each, that is 100,000 score calculations every 15 minutes, which is manageable on standard Cloud Function capacity.

Can RapidDev help build a custom feed ranking system?

Yes. RapidDev can implement advanced ranking algorithms with machine learning models, real-time personalization, A/B testing infrastructure, and analytics dashboards to monitor feed quality.

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.