Adding Stream Feeds to the Timeline
Scaling activity feeds is hard when you have many users. Stream’s API leverages Go, RocksDB & Raft to ensure great performance (<10ms) and scalability. It hides the complexity of push, pull, fanout on read, and fanout on write behind an easy-to-use API. Apps such as Soundcloud, eToro, Under Armour, and Dana rely on Stream for their activity feeds.
In this second part of the Twitter Clone tutorial series we’ll add Stream feeds to enable users to send, receive, subscribe, or unsubscribe from others' timelines. Refer to the first part of the this tutorial, Building the Timeline, to learn about the overview of the project's architecture and the setup process.
💡 You must have a Stream account and API key for Feeds before continuing. You can create a free account on Stream here.
Find the project demo and download the source code from GitHub.
Overview of Stream Feeds
Using the Stream's Activity Feeds components, you can build timeline feeds with real-time updates that support likes and comments, similar to the timelines of Instagram or Twitter.
Feeds Setup
The main component of the app is a Twitter-like user experience where users can post messages, and other people can subscribe to receive those messages. It may sound like something perfectly suited for Stream’s feed product. The Stream Feeds App will handle all the heavy lifting as a backend to ensure users can create activities, subscribe/unsubscribe to other users’ updates, and more.
We created three feed groups in Stream Feeds’ backend to get the functionality. In the application, we need to have a:
- "timeline" feed group for activities made by users that a user follows
- "user" feed group for activities by a user
- "notification" feed group for notification activities originating from follow or reaction actions
The biggest thing to understand is that a user follows another user by subscribing to their timeline feed to another user’s user feed.
In the timeline and user group, we use a flat feed type and a notification group with a notification feed type.
In our codebase, everything directly related to Feeds is in the TimelineUI and the Feeds Packages. In your downloaded TwitterClone project, find the TimelineUI in the Project Navigator. Open the following Swift files to explore the code samples related to feeds. Below are a few examples
FeedsView.swift
ProfileInfoAndTweets.swift
MyProfileInfoAndTweets.swift
From our dependency graph below, the app's targets depend on the HomeUI package. The HomeUI package is the central hub of our app. Everything starts from the HomeUI. Additionally, the HomeUI is only invoked by the app class if the user has logged in. Otherwise, we send the user to the signup/login flow.
NodeJS Server
Next to the Stream backend, we need a way to authenticate users and fetch Tokens on their behalf. To facilitate this, we created a small NodeJS backend, which we deployed to Digital Ocean. It is not much more than a Database with a user table and some code to isolate this database from the internet. In a previous blog post, Minimal Node Integration to Get You Started with Stream, we wrote about this integration layer.
To have convenient persistent availability of our NodeJS backend, we opted to deploy to Digital Ocean using a managed PostgreSQL instance combined with their “App” offering. It brings us two benefits. First, we get access to a scalable infrastructure with the convenience of Git push deployment. Check Digital Ocean’s offerings to see a lot of powerful components at several levels of abstraction.
As mentioned, we use the NodeJS server described as described in our previous blog post. But we did extend the its functionality a lot. Most important, the version in the blog post uses a local SQLite database for convenience. Since we are deploying to Digital Ocean and are using their PostgreSQL offering, we migrated the code of the NodeJS server to work on this infrastructure. On top of that we extended the NodeJS codebase significantly to facilitate in several backend related tasks we need to have for our implementation. Things like feeding Stream Feed Webhook calls into our search API provider Algolia. All code related to our additional work is being kept on a separate branch to make sure the basic SQLite implementation remains untouched. To have a look at our actual backend code deployed to Digital Ocean, have a look at the “postgresql” branch of the GetStream/stream-node-simple-integration-sample repository.
Build the Add a New Tweet View
You can add a new tweet to the timeline using the floating Add a new tweet button at the bottom right of the home view. Tapping the button launches a new screen to compose your tweet. When you send the tweet, it appears as the most recent timeline item. Check out the code below from the HomeUI in the Project Navigator and explore how we build the add a new tweet view.
The code below uses hard-coded data, but we will update this to use dynamic data once we implement user profiles.
AddNewTweetView.swift
Build the For You Feeds View
In the For You Feeds View, we fetch two feed categories from our feed client. Here, we display user-specific feeds and timeline feeds. Open ForYouFeedsView.swift
from the Sources folder under HomeUI to explore the code.
ForYouFeedsView.swift
As you can see from the code above, the UI is displayed using a list and the content from PostRowView.swift
. The list of items gets updated by fetching data about the updated activities from the feed client.
Create the Post Row View
The Post Row View shows data about a single tweet, like user name, profile image, number of likes, and retweets. The PostRowViewViewModel contains the data used to populate the post-row UI. To create this view, refer to PostRowView.swift in the HomeUI of the Project Navigator.
Conclusion
This tutorial introduced you to adding Stream Feeds to the timeline to build a twitter-like home page feeds experience. To get the best out of the TwitterClone tutorial series, we encourage you to read the following tutorial about Enabling Support For Media Tweets and Video Playback.