FCC Speedrun #2 — Voting App
Project 2 — The voting app.
Day 1 — Well, this is rather daunting.
Creating a full stack app from scratch, that is. Breaking it down into smaller chunks, it seems that authentication is the first thing to do, only I have no idea how to do it. Fortunately FCC provides a boilerplate template for creating these apps — it’s called clementine.js. The setup instructions are for cloud9, but I’m using glitch.com, so there are a few differences — I’m not running mongoDB locally, I’m accessing it on mLab; plus the env variables are slightly different. I make a few adjustments, fire up the homepage, and to my surprise I am able to log in. What sorcery is this? No seriously, how did that work?
Conceptually, it makes sense to me, so I tried to reverse engineer the code. But after researching sessions, passport, strategies, GitHub authorization, I am no closer to enlightenment. For me, the only way to proceed was to start over and build it again without the boilerplate template, step by step. Some searching brought me to this tutorial: http://mherman.org/blog/2015/09/26/social-authentication-in-node-dot-js-with-passport/#.WPjMkVPysy4 which was clearer to me, and I was able to recreate the login process on my own. Success! It still feels like magic, but now I’ve pulled back the curtain ever so slightly.
Having conquered authentication, the next hurdle I decide to tackle is the data structure for the app. I need to impose a simple structure that fulfills the user stories, but keeps my tendency for scope creep at bay. I already have a user collection in Mongo, that looks like this:
VotingUser = {
github: {
id: String,
username: String,
displayName: String,
public_repos: Number
}
}
The only other object I need is a Polls object. Polls will have an owner, and they will have an array of Options and they will have an array of users who have cast a vote. Each Option will have a description and a vote count. So the Poll object will look like:
Poll = {
owner: _id,
options: [{
description: String,
voteCount: Number
}],
voters:[]
}
Day 2–4 Frustration
I got frustrated here by the issue of keeping my React front end state in synch with my server session, then didn’t have time to work on it for a couple of days. The issue is that when using social login from GitHub, the server redirects the client to a callback URL, and the React app refreshes, losing state. So if the user does some navigation prior to logging in, then their state will reset. This really confused me for a long time — when the state was lost, I thought it meant that I wasn’t logged in, although that wasn’t true. Lesson learned: Here, a better design from the beginning would have saved me hours (days) of trouble.
I’m not sure if the solution I landed on is *right* or even _good_, but it works. I set up a route on the server to return some session info, and then in ComponentDidMount() on the client I get the session data and set my state. Successful login/logout felt like a monumental achievement!
Day 5–6 — Progress
I started building my APIs to Vote on Polls, Add new Surveys, Delete, etc. Around this time I realized what a mess my user interactions were. At this point, I decided that React-Router would help provide a consistent flow. I have resisted React Router for a long time, but finally took the plunge. There are several versions of this package which makes troubleshooting difficult, but overall this step was definitely worth the time invested .
OK, all my functionality seems to be in place, so I can spend a little time todayworking on styling the app. So many hours trying to make a sticky footer before giving up! For me, styling takes a lot of time to work out — I rarely have a clear vision to execute, so it involves a lot of trial and error. Ultimately that is not compatible with the speedrun goals, so I’m leaving style to a minimum and calling this app done.
You can check the finished product here: https://dg-voting.glitch.me/
and view the code on Glitch: https://glitch.com/edit/#!/dg-voting
Thanks for reading!