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

How to Design a News Aggregator Platform in FlutterFlow

Build a news aggregator that fetches articles from multiple RSS and API sources via a scheduled Cloud Function, normalizes them into a Firestore articles collection, and displays them in FlutterFlow with category TabBar navigation. Each tab shows a ListView of article cards sorted by publish date. Users can tap to read articles in an in-app WebView or open them externally. A bookmark feature saves articles to a user subcollection. The Cloud Function runs hourly, deduplicates by URL, and parses RSS XML into structured Firestore documents.

What you'll learn

  • How to fetch and normalize RSS feed articles using a scheduled Cloud Function
  • How to display categorized articles with TabBar navigation and ListView
  • How to read articles in-app using a WebView Custom Widget
  • How to implement an article bookmark system with Firestore
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

Build a news aggregator that fetches articles from multiple RSS and API sources via a scheduled Cloud Function, normalizes them into a Firestore articles collection, and displays them in FlutterFlow with category TabBar navigation. Each tab shows a ListView of article cards sorted by publish date. Users can tap to read articles in an in-app WebView or open them externally. A bookmark feature saves articles to a user subcollection. The Cloud Function runs hourly, deduplicates by URL, and parses RSS XML into structured Firestore documents.

Building a News Aggregator Platform in FlutterFlow

This tutorial creates a news aggregator that pulls articles from multiple sources, organizes them by category, and presents them in a clean reading interface. Unlike a single-source RSS reader, this platform aggregates from multiple feeds, deduplicates articles, and stores them in Firestore for fast querying. Users browse by category, read articles in-app, and save favorites. This pattern works for industry news portals, content curation apps, and company internal news boards.

Prerequisites

  • A FlutterFlow project with Firestore configured
  • Firebase Cloud Functions enabled (Blaze plan)
  • At least 3-4 RSS feed URLs to aggregate
  • Basic understanding of TabBar and ListView in FlutterFlow

Step-by-step guide

1

Create the Firestore data model and identify RSS sources

Create an articles collection with fields: title (String), summary (String), imageUrl (String), sourceUrl (String, the original article link), sourceName (String, e.g., 'TechCrunch'), category (String: Tech, Business, Sports, Science, Entertainment), publishedAt (Timestamp), fetchedAt (Timestamp). Create a users/{uid}/saved_articles subcollection with fields: articleId (String), savedAt (Timestamp). Identify 3-4 RSS feed URLs for your categories. Store them in a feed_sources collection with fields: url (String), sourceName (String), category (String), isActive (bool).

Expected result: Firestore has articles, feed_sources, and saved_articles collections ready for the aggregation pipeline.

2

Build the Cloud Function to fetch and normalize RSS feeds

Create a scheduled Cloud Function that runs every hour. The function reads all active feed_sources documents, fetches each RSS feed URL using node-fetch or axios, parses the XML response using the xml2js package to extract title, link, description, pubDate, and any media content URL for the image. For each parsed entry, check if an article with the same sourceUrl already exists in Firestore to deduplicate. If it is new, create an articles document with the normalized fields including the source category. Set fetchedAt to the current server timestamp. Log the count of new articles added per run.

fetchNewsFeeds.js
1// Cloud Function: fetchNewsFeeds (scheduled hourly)
2const functions = require('firebase-functions');
3const admin = require('firebase-admin');
4const axios = require('axios');
5const { parseStringPromise } = require('xml2js');
6admin.initializeApp();
7
8exports.fetchNewsFeeds = functions.pubsub
9 .schedule('every 1 hours')
10 .onRun(async () => {
11 const sourcesSnap = await admin.firestore()
12 .collection('feed_sources').where('isActive', '==', true).get();
13
14 for (const sourceDoc of sourcesSnap.docs) {
15 const { url, sourceName, category } = sourceDoc.data();
16 try {
17 const res = await axios.get(url, { timeout: 10000 });
18 const parsed = await parseStringPromise(res.data);
19 const items = parsed.rss?.channel?.[0]?.item || [];
20
21 for (const item of items.slice(0, 20)) {
22 const sourceUrl = item.link?.[0] || '';
23 const existing = await admin.firestore()
24 .collection('articles')
25 .where('sourceUrl', '==', sourceUrl).limit(1).get();
26
27 if (existing.empty && sourceUrl) {
28 await admin.firestore().collection('articles').add({
29 title: item.title?.[0] || '',
30 summary: (item.description?.[0] || '').replace(/<[^>]*>/g, '').slice(0, 300),
31 imageUrl: item['media:content']?.[0]?.$?.url || '',
32 sourceUrl,
33 sourceName,
34 category,
35 publishedAt: admin.firestore.Timestamp.fromDate(
36 new Date(item.pubDate?.[0] || Date.now())
37 ),
38 fetchedAt: admin.firestore.FieldValue.serverTimestamp(),
39 });
40 }
41 }
42 } catch (e) {
43 console.error(`Failed to fetch ${sourceName}: ${e.message}`);
44 }
45 }
46 });

Expected result: The Cloud Function fetches RSS feeds hourly, deduplicates articles, and stores new ones in Firestore.

3

Build the news feed with category TabBar and article cards

Create a NewsPage. Add a TabBar with tabs for each category: Tech, Business, Sports, Science, Entertainment, and an All tab. Each tab contains a ListView bound to a Backend Query on the articles collection filtered by category (or no filter for All), ordered by publishedAt descending, with a limit of 20 documents. Each article card Container shows: the imageUrl on the left as a small thumbnail, the title in bold, the summary truncated to 2 lines, a Row with sourceName and a relative time label (e.g., '2 hours ago'). Add a pull-to-refresh RefreshIndicator that re-runs the query.

Expected result: Articles display in category tabs with thumbnails, titles, summaries, and source labels.

4

Add in-app article reading with WebView and bookmarks

Tap an article card to navigate to an ArticleReaderPage with Route Parameter articleId. Query the article document. Display the title and source name at the top, then embed a Custom Widget WebView that loads the sourceUrl for the full article content. Add a bookmark IconButton in the AppBar. On tap, check if a saved_articles document exists for the current user and articleId. If not, create one with savedAt timestamp. If it exists, delete it. Fill the icon when bookmarked. Create a SavedArticlesPage that queries the user's saved_articles subcollection, joins each articleId to the articles collection, and displays them as the same card layout.

Expected result: Users can read articles in-app via WebView and bookmark favorites for later reading.

5

Add search and source management

Add a search TextField at the top of the NewsPage above the TabBar. On text change, filter the current tab's query by title prefix match (where title >= searchTerm and title <= searchTerm + unicode high char). For admin users, create a SourceManagementPage that lists all feed_sources with their name, URL, category, and an isActive Switch toggle. Add a form to create new feed sources. Changes to feed sources take effect on the next hourly Cloud Function run. Display the last fetchedAt timestamp so admins know when articles were last updated.

Expected result: Users can search articles by title, and admins can manage RSS feed sources.

Complete working example

FlutterFlow News Aggregator Setup
1FIRESTORE DATA MODEL:
2 feed_sources/{sourceId}
3 url: String (RSS feed URL)
4 sourceName: String
5 category: String (Tech / Business / Sports / Science / Entertainment)
6 isActive: bool
7
8 articles/{articleId}
9 title: String
10 summary: String (max 300 chars, HTML stripped)
11 imageUrl: String
12 sourceUrl: String (original article URL)
13 sourceName: String
14 category: String
15 publishedAt: Timestamp
16 fetchedAt: Timestamp
17
18 users/{uid}/saved_articles/{docId}
19 articleId: String
20 savedAt: Timestamp
21
22CLOUD FUNCTION: fetchNewsFeeds
23 Schedule: every 1 hour
24 Flow:
25 1. Read active feed_sources
26 2. For each source: fetch RSS URL parse XML
27 3. For each item: check dedup by sourceUrl
28 4. If new: create articles doc with normalized fields
29
30PAGE: NewsPage
31 WIDGET TREE:
32 Column
33 TextField (search)
34 TabBar (All / Tech / Business / Sports / Science / Entertainment)
35 TabBarView
36 Per tab:
37 RefreshIndicator
38 ListView (articles, orderBy publishedAt desc, limit 20)
39 ArticleCard Container
40 Row
41 Image (thumbnail, 80x80)
42 Column
43 Text (title, bold, max 2 lines)
44 Text (summary, max 2 lines)
45 Row (sourceName + relative time)
46 On Tap: navigate to ArticleReaderPage
47
48PAGE: ArticleReaderPage
49 Route Parameter: articleId
50 WIDGET TREE:
51 Column
52 Row (title + bookmark IconButton)
53 Text (sourceName + publishedAt)
54 Custom Widget: WebView (sourceUrl)
55
56PAGE: SavedArticlesPage
57 Backend Query: saved_articles subcollection
58 ListView (same ArticleCard layout)

Common mistakes when designing a News Aggregator Platform in FlutterFlow

Why it's a problem: Fetching RSS feeds from the FlutterFlow client instead of a Cloud Function

How to avoid: Fetch feeds in a scheduled Cloud Function and store normalized articles in Firestore. The FlutterFlow client only reads from Firestore.

Why it's a problem: Not deduplicating articles by sourceUrl before writing to Firestore

How to avoid: Before creating an article document, query Firestore for an existing document with the same sourceUrl. Only write if no match exists.

Why it's a problem: Storing raw HTML from RSS descriptions without stripping tags

How to avoid: Strip HTML tags from the summary in the Cloud Function using a regex like replace(/<[^>]*>/g, '') before saving to Firestore.

Best practices

  • Fetch and normalize RSS feeds server-side in a Cloud Function, never from the client
  • Deduplicate articles by sourceUrl before writing to prevent duplicate entries
  • Strip HTML tags from RSS descriptions for clean text display
  • Use category-based TabBar for organized browsing with each tab querying independently
  • Limit article queries to 20-30 items per page for fast loading
  • Show relative timestamps like '2 hours ago' instead of absolute dates for freshness context
  • Store feed sources in Firestore so admins can add or remove sources without code changes

Still stuck?

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

ChatGPT Prompt

I want to build a news aggregator in FlutterFlow that fetches articles from RSS feeds using a scheduled Cloud Function, stores them in Firestore with deduplication, and displays them with category tabs, article cards, in-app WebView reading, and bookmarks. Give me the data model, Cloud Function code for RSS parsing, and FlutterFlow widget tree.

FlutterFlow Prompt

Create a news feed page with category tabs at the top (Tech, Business, Sports, Science, Entertainment), a list of article cards below each tab showing a thumbnail image, title, summary, and source name, and a floating bookmark icon on each card.

Frequently asked questions

How often should the Cloud Function fetch new articles?

Hourly is a good default. For breaking news sources, consider every 15 minutes. For slower-moving categories, every 4-6 hours. Balance freshness against Cloud Function invocation costs.

Can I add article images if the RSS feed does not include them?

Yes. In the Cloud Function, if media:content is empty, fetch the article page HTML and extract the Open Graph image meta tag. Store that URL as imageUrl. This adds processing time but improves the visual experience.

How do I handle feeds that require authentication?

Store API keys or credentials in Cloud Function environment variables. Pass the credentials as headers in the fetch request within the Cloud Function. Never expose credentials to the client.

Can users submit their own RSS feeds?

Yes. Add a form where users submit a feed URL. Validate the URL by attempting to parse it in a Cloud Function. If valid, add it to feed_sources with a review or auto-approve workflow.

How do I clean up old articles to manage Firestore costs?

Create a scheduled Cloud Function that deletes articles older than 30 days. Also delete corresponding saved_articles entries to prevent broken bookmarks. Run it daily during low-traffic hours.

Can RapidDev help build a full content aggregation platform?

Yes. RapidDev can build news platforms with ML-powered personalization, push notification alerts for breaking news, social sharing, reading analytics, and multi-language content support.

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.