Muffin Tutorial: Build a Twitter Clone (Part 1)
In this tutorial we will use Muffin to build a simple social networking app. Since our goal is to demonstrate how to use Muffin, we would like to focus on the core features of social networking apps. In that regard, what could be a better choice than building a Twitter clone?
Note that we are not building yet another Twitter client, but a full-blown Twitter clone with both frontend and backend. All the project code can be found in this GitHub repository, and the git commit history largely follows this tutorial.
Building a clone means that a lot of design work has already been done for us, but we still need a strategy. We are not going to replicate every single feature of Twitter, so we need to think about which features are essential, and which ones are not.
Let’s take a look at the real Twitter.
Twitter’s home page is quite simple, with just a full screen image as the background and a login form.
After logging in, Twitter’s main UI looks like this:
Again, the UI is quite simple: a navigation bar on top, an account summary on the left, and a list of tweets on the right.
The “@Connect” and “#Discover” screens are just variations of the main screen, so we are going to skip those. The compose screen looks like this:
And the profile screen looks like this:
Here you can view a list of my tweets, or a list of people I am following, or a list of my followers, etc.
Inside settings, there are “lists”, “direct messages” and “help”. Direct messages are just variations of tweets, so we are going to skip those as well.
It seems that the essential features of Twitter include:
- A login screen.
- Compose a new tweet.
- View a list of tweets from me and people I follow.
- View a list of people I am following.
- View a list of my followers.
- Follow/unfollow people.
- Profile summary.
Other features in Twitter are more or less variations of the above. So let’s focus on implementing these essential features in our Twitter clone. Also, we are not going to implement another user registration system, because we all have way too many accounts already. We are going to let users sign in with their Google Accounts instead.
We also need to think about mobile. Twitter’s website doesn’t use a responsive layout, so it doesn’t work well on mobile. But you can download Twitter’s native mobile apps. The new Twitter app for iOS 7 looks like this:
The mobile interface actually isn’t too different from the desktop interface. Maybe we can create a single responsive layout that works well on both desktop and mobile.
Create a new project
Since we are building a full-blown Twitter clone with both frontend and backend, we need to pick a server stack. Muffin comes with two preferred server stacks: Google App Engine and Node.js/MongoDB. In this tutorial we are going to pick Node.js/MongoDB, simply because we picked Google App Engine in the RSS Reader tutorial.
Creating a new project with Muffin takes just one line:
We have named our project
parrot and specified the server stack as Node.js/MongoDB. Why “parrot”? Well, you will know soon.
Now install the dependencies:
Since we are using Node.js/MongoDB as the server stack,
muffin install also automatically calls
npm install inside the server directory to install all the server dependencies.
Let’s put everything under version control:
Now start the server while watching files:
This starts a Node.js server at
http://localhost:4000. Open the URL in your browser and you should see the app in action.
Great! Our new webapp is up and running.
App name and app icon
Now that we have the project boilerplate set up, let’s change the app name and app icon.
You need to change the app name in two places: in
title Webapp to
title Parrot, and in
title: "Webapp" to
For the app icon, we are not going to use Twitter’s blue bird, because that would be a trademark violation. Since we are going to let users sign in with their Google Accounts, let’s add some Google colors to the bird. The final design looks like this:
Now you know why we named our project “parrot”!
It’s time to get down to business. First we need to create the main application layout. Our strategy is to create a responsive layout that adjusts well on both desktop and mobile.
On the desktop, the main layout consists of a navigation bar on top, an account summary on the left, and a list of tweets on the right. On mobile devices, the main layout consists of a top navigation bar, a list of tweets, and a tab bar at the bottom. We are going to let the list of tweets auto adjust to the screen width, but hide or show the navigation bar or tab bar.
LayoutView.jade with the following:
Also add the styles in
This is how it looks on the desktop:
And this is how it looks on my iPod Touch:
The responsive layout works like a charm! The desktop layout mimics Twitter’s website layout quite nicely, and the mobile layout looks very similar to Twitter’s iOS 7 native app, except that we changed the color scheme to better fit our “parrot”.
The app layout looks nice but it’s kind of empty. Let’s add some real contents to it. The right side of the desktop layout should show a list of tweets from me and people I follow, so let’s implement that.
First, we need to create a data model for the tweets. Let’s use Muffin’s scaffold generator to quickly create a fully functional CRUD prototype:
Muffin generated a list of files including client models and views, server models and controllers, as well as routers. Now navigate to
localhost:4000/#tweets and you should see this:
Create a new tweet by pressing the “Add New Tweet” button. You can also edit or delete a tweet. I just added a couple and this is how my screen looks now:
If you turn on Chrome’s developer console, you can see that we are indeed making API requests to the server:
It’s great to have a working CRUD prototype, but the interface isn’t what we had in mind. Let’s make some changes.
Remove the view files that we won’t use, including
TweetShowView. You can use
muffin destroy to do this:
We do need a tweet list view, but the auto-generated
TweetIndexView is too lengthy. So let’s generate a clean one:
Copy over just the following from
TweetIndexView into our newly minted
Now we can remove the auto-generated
To keep the code modular, we will create another view class
IndexPage to manage the main view. In Part 2 we will create another view class
ProfilePage for the profile page.
Move the following from
IndexPage also acts as a mediator between the left side of the main layout and the list of tweets. We will see this shortly.
Now we need to update the routes in
client/apps/main/router.coffee. Remove the auto-generated routes for tweets, then replace the
index function with the following:
We haven’t made any visible change to the main screen yet. But we are almost there. Let’s flesh out the
TweetListView. Add the following to
TweetListView in the index page, add the following to the
initialize function of
Now we just need to render the list of tweets inside
TweetListView.coffee to the following:
We also need to add a partial
Finally, add the following styles to
Let’s take a look at what we have achieved. This is how the app looks on the desktop:
And this is how it looks on the iPod Touch:
The app looks awesome on both desktop and mobile.
Compose a tweet
We need to show the compose view in a lightbox, so let’s install a decent lighbox implementation first — Lightbox_me. Add the following shim to
client/config.json, inside “dependencies”:
muffin install, and
Lighbox_me will be installed inside
Now we need to create the compose view. Let’s use
muffin generate to do that:
Add some styles in
We also need to add an event handler to
It’s time to see the compose view in action. This is how it looks like on the desktop:
And on my iPod Touch:
Great! It looks just like the real thing. But we still need to make it functional.
ComposeView.coffee and implement event handlers for updating the character count and sending a tweet.
We also need to add a few convenient functions to
You might have also noticed that the tweets are not sorted in the reverse chronological order, so let’s fixed that in
Great. It’s all done. Try it on your desktop browser or mobile devices. You should see the character count change as you type, and the “Tweet” button is enabled only if you have entered between 1 and 140 characters.
Now we can remove the auto-generated
We have done pretty well in this part of the tutorial, so let’s call it a day. In the next part of this tutorial, we will implement Google authentication, the profile page, and follow/unfollow people.