Finishing an Eminem fan app in a weekend using GraphQL and Expo
Blog

Finishing an Eminem fan app in a weekend using GraphQL and Expo

+tldr; I’ve started many programming side projects in the last year, but none that I ended up actually finishing. Last weekend I made it my mission to finish building a usable app and submit it to the app stores. I had to make some unorthodox decisions like momentarily backing off from GraphQL and delivering content through hot code push (more on that later). This post is about my journey on managing my time as a programmer/self-manager and the technical decisions that I had to make in the process of creating a usable app – all in a single weekend. I hope that this post helps to motivate you to finalize your side projects, or at least one of them.

The idea

I looked at the time. It was 6:00 pm on a Friday and that only meant one thing: I was done work. Like many other developers, I was filled with relief and excitement to go home and get ready to join my friends at the bar. This was only until I remembered that I don’t have any friends, I work from home, and I’m not wearing any pants. I checked Eminem’s subreddit to check on any news on the new album – no news. Sadness ensued.

img-2

This gave me an idea to create an app that would send me push notifications of any new album updates. This would eliminate the need for constantly visiting the Eminem subreddit on Chrome or the Reddit app.

What will the app do?

The app will be able to

  • Send a push notification to the users once there are new songs or news
  • Display all the news items in a feed with a thumbnail
  • Allow the user to open the news items by either opening the in-app browser or going to the appropriate app (e.g. Reddit, Instagram, Youtube, Twitter, etc)
  • Allow an admin to update the content

This is how it ended up looking after the first weekend:

demo

The next step was for me to pick a tech stack to use.

Why only over a weekend?

You only have short sessions here and there, rather than continuous 8-hr workdays to work on your side project. If you give yourself a task that takes 5 days to finish, even if you spend a lot of your free time on your side project, you’ll have to wait a long time before you can claim a win. Dragging your task over the span of multiple weeks rather than a few hours means that you’ll be working on an “incomplete” task for many of your sessions rather than starting and stopping tasks.

This is more important for side projects than ongoing projects because you can’t pick up where you left off. The last time you worked on it might be last weekend, or a month ago. It’ll take you a few minutes to realize what you were trying to do, see what parts are done, what is left to do, and by the time you are warmed up, your 1 hour of free time is gone and you have to take your aunt to Costco.

If you make it your mission to “finish” your app over a weekend you will be able to:

  • Quickly evaluate if anyone is even interested in downloading and using your app
  • Feel rewarded for smaller, winnable goals
  • See the big picture and not get lost in implementation details

Pick something familiar!

Since my goal was to quickly finish the app and submit it to the app store, I picked Expo as my main framework. Expo is built around React Native and it comes equipped with a lot of tools that allowed me to host my data, images, and send push notifications (this is instead of me having to research for packages for each little thing).

I’ve been using Expo for several months now at OK GROW! as well as on personal projects. It’s tempting to try new things for your side projects, but for me, the goal was to bring my project to completion rather than to learn a new thing, so I decided to stick with it.

5.gif

Since it’s a React Native app, I write everything in Javascript. It easily gives me ways to grab my .apk or .ipa and submit it to the store without even having to open Android Studio and XCode (my RAM heaves a sigh of relief).

What about Push Notifications?

Expo makes it super easy to send push notifications. But this was one of those things that I couldn’t just hack around without a backend. You need a backend to store a token for each person’s phone. I tried dodging this by using Graph.cool as a backend database, but I’d still need to integrate a GraphQL connection both on the phone and on my server to transmit the information and send the push notifications, and ain’t nobody got time for that! 6.png

GraphQL yay or nay?

Since it’s 2017, initially I thought I’d use the newest and greatest API between the phone and my database which is GraphQL. I actually was naive enough to start writing some queries and mutations. Let’s observe one of these cute mutations:

const createUserMutation = gql`
  mutation(
    $pushToken: String!
    $subscribedToNews: Boolean!
    $subscribedToMemes: Boolean!
  ) {
    createUser(
      pushToken: $pushToken
      subscribedToNews: $subscribedToNews
      subscribedToMemes: $subscribedToMemes
    ) {
      id
      createdAt
      subscribedToNews
      subscribedToMemes
      pushToken
    }
  }
`;

And then another mutation that uses an undocumented graph.cool function called updateOrCreateUser, and then I was considering firing my own database and graphQL server…

This is when I realized I only have one call in my API, so it doesn’t really need a GraphQL Server. I just need a secure way to tell my backend to remember about me, and Meteor allows me to do that in a few lines. This is almost all of my Meteor server:

shocked-gif

import { ValidatedMethod } from 'meteor/mdg:validated-method';
Tokens = new Mongo.Collection('tokens');
export const updateText = new ValidatedMethod({
  name: 'createUser',
  validate: new SimpleSchema({
    pushToken: { type: String },
    subscribedToNews: { type: Boolean },
    subscribedToMemes: { type: Boolean }
  }).validator(),
  run({ pushToken, subscribedToNews, subscribedToMemes }) {
    Tokens.upsert(pushToken, {
      $set: { pushToken, subscribedToNews, subscribedToNews }
    });
  }
});

Did I pick an inferior solution just because I’m lazy to do thing the proper way? Maybe, but don’t judge me too quickly.

My next session, which was two weeks later, was spent bringing GraphQL back using the very mutations that I’d mocked a week ago. The point here is that there may be a greater solution which takes more time to write. For an ongoing project it might be worth taking a step back and implement this greater solution which is the GraphQL abstraction layer. But it’s probably a bad idea if your goal is to not leave your app at an unfinished state at the end of your session.

Content delivery

Once again, I started delivering my content using the simplest method. Expo allows me to send updates to my Javascript code without the user having to update their app through the store. This allows me to use code push to deliver my data, instead of using a database. There are also alternative services that do similar things like Microsoft’s CodePush.

This might not be the most common way to use Expo’s code push, but it will allow me to create a static app in a way that mirrors how Github Pages or Jekyll blogs work. I write my content in a file, press Publish in Expo’s XDE, and once the user opens the app, they receive an update! This means Expo hosts the data for me because it’s treated like a code, and it also uploads my assets such as thumbnail images to a CDN.

This saves me hours of having to set up a CMS or database, and an admin portal, and having to find a way to host my assets on a CDN sever.

Later on, I converted to delivering the content through GraphQL, but again, I had to skip this momentarily in order to “finish” the app over the first weekend.

How is the UI looking so pretty?

As a UI expert, my first step towards designing a good UI was googling for React Native UI component kits. There are a bunch listed here:

https://stackoverflow.com/questions/34640902/is-there-a-ui-component-kit-for-react-native-like-ionic-framework

8.png

Obviously, out of that list the word kitten gravitated me towards: https://github.com/akveo/kittenTricks, Which I ended up using.🐈 🐈🐈 Mostly because they had good documentation and a working React Native example.

9.png

I had originally planned 30 minutes to spend on the Logo. Turns out 30 minutes is not enough time to beg your girlfriend to make you a logo, even though she promised she’d do it if you washed the dishes. I ended up mashing google’s devil emoji with an Eminem picture and ended up with this. Google, please don’t sue me.

Cost

  • Server/Database: Since Heroku allows me to easily set up Meteor with a Mongo database for free, I have no database or server costs. Using Heroku’s free tier means small resources, but that should not become a scaling problem for a while because the server will only get pinged when a user changes their settings, which shouldn’t happen too often. So unless all of the users suddenly plan to spam the settings buttons…

evil-gif

Did I actually finish?

I got started early on Friday evening and got pumped to work on this all weekend. Once I got the base skeleton done I thought it was a great reason to celebrate. Saturday morning proved otherwise, and I ended up waking up at noon with half of the day gone. But I decided to stay optimistic, and on Sunday I got the majority of the server and front-end work done. And who would have thought, my app was in the store by Monday! Guess I’m not that bad at finishing side projects after all - it’s all about a clear plan and motivation.

Now I just have to write a script that picks the top news from Reddit every morning, which is what I did in my 2nd session, before finally introducing GraphQL to my app.

success

Link to android app: https://play.google.com/store/apps/details?id=com.arrygoo.shadynews

We'll share what we've learned, get tips and info in your inbox occasionally