MLH Fellowship Hackathon - Voting Information Project
For the first-week hackathon project, I wanted to build a webapp that will allow people to find as much useful information on how and where to vote as possible. Voting is a right that is incredibly important to me, and I wanted my first project with MLH to reflect that. My gripe with most services that are already doing this is that they only have some information and I end up having to go to 2-3 websites to find everything. I'm trying to correct this by giving you all the relevant information needed!
How I Built It
This was a difficult project! It's the first time I've ever used HTML, CSS, or a web framework like flask, since most of my work has been on backend systems. I was also working alone due to a series of unfortunate events, namely my apartment building's fiber cable being accidentally cut by nearby construction right as the hackathon began.
The first thing to do was to figure out what information I wanted to give the user, and how to get it. There were three aspects I wanted to focus on: voter registration, finding the nearest polling places, and finding the nearest USPS mailboxes so that you can return your mail-in ballot. I tackled the mailbox problem first; luckily, I found an amazing repo with every mailbox in the US packed into a csv, including data such as its address, latitude, and longitude.
I converted this into a sqlite3 database quickly with some more code, which can be found in
dbi.py. I then started working how to figure out which three nearest mailboxes were closest to the given address. I used Haversine's formula for this, which allows the program to quickly calculate the distance to each mailbox and then select the 3 with the shortest distance.
The next part was to figure out how to get registration links for every state. As it turns out, vote.gov has all the links you need, with standardized HTML tags! I built a webscraper using Beautiful Soup to find the links for every state, and then I inserted that into my USPS database as a new table. Finally, I found the nearest polling places and early voting sites using Google's Civics Information API which gave me all the information I needed.
The Hard Part
The biggest challenge in this project for me, by far, was designing a decent frontend. I've never done it before, so it was extremely difficult! Once I built a decent front page, I came across the next challenge: making it dynamic. Luckily, flask and jinja (the template engine flask is built on top of) make it extremely easy to do this. I created a function to tie every data source together into a uniform dictionary object that could pass all the information to jinja to render into the webpage, which it now does nicely. Finally, I pieced together some CSS into the main webpage to make it look a little nicer and more readable. For some reason I couldn't get the CSS to work on the page with the returned information, and I ran out of time before I could figure it out, so please forgive the eyesore it may be!
So... Does it Work?
Yes! There are still a few bugs to fix, but the functionality is all there. You start it by running going into the source directory in your command line and entering
python3 app.py [key], where
[key] is your Google API key (you can get one (here)[https://console.cloud.google.com/projectselector2/home/dashboard]). It will start up the server and you can enter your address into the webpage!
This webapp is built on flask, a lightweight framework for Python. It also makes heavy use of an sqlite3 database, something that's included in the github repo! (Warning, it's >32MB and has over somewhere around 200,000 rows.)
- requests (HTTP for Python)
- bs4/beautifulsoup (webscraper framework)
- usaddress (parses and validates addresses)
- flask (webapp framework)
- re (regex)
- sys (the system requires a google API key, input through the command line)
- csv (csv handling)
The only input is a valid address, nothing more.
From there it will give a bunch of useful info, including registration info for your state, your polling place, where you can vote early, and where the 3 closest USPS boxes are to mail-in your ballot. It does this through rendered templates, an awesome feature in flask which allows you to change your webpage dynamically.