With the dust finally settling from TransparencyCamp, it's a good time to talk about some of the work we did this time around to prepare for one of our favorite weekends of the year. TCamp '13 was a year of firsts for us: our first 500+ crowd, first time running the event with a mostly volunteer staff, and our first time trying to run nearly everything digitally and online. In this post I'll run through the what/why/how of that last point, and touch on some lessons learned. It's gonna be long and Django-centric, so grab your pink pony mug and cozy up with a cup of coffee.
Last Monday we launched an update to our Capitol Words project, which indexes and tokenizes the Congressional Record daily. With the launch behind us and the dust starting to settle, I'd like to walk through how we get from raw text to attributed, searchable quotations, and provide some examples of how you can interact with the data directly.
Before delving into how it works, though, it's important to acknowledge the myriad developers whose work on this project has made it possible. I'm only the most recent steward of the site; the bulk of the data legwork for this iteration was handled by Aaron Bycoffe and Jessy Kate Schingler, and the web interface owes its beauty to Caitlin Weber and Ali Felski. Timball provided the hardware, and the list continues from contributions to the scrapers all the way back to the original conception and implementation of the idea by Josh Ruihley and Garrett Schure. It's the combined efforts of everyone involved that brought us the site that's available today.
Now, without further ado...
As part of the 2nd Annual Labs Olympics, Team Leaf Peepers built NiceNeighbor, a network designed to put helpful neighbors in contact with each other.
It's been an interesting couple of months on the East Coast and in the DC area in particular, with earthquakes, torrential rains and flooding, terror threats and even a 2-0 start to football season in the mix leaving Washingtonians confounded, confused and generally insecure. Amidst these troubling times we've observed a pattern: In the face of uncertainty, people can tend to be jerks to each other. We hoard things, Jam up the roads and grocery aisles, and get pushy and rude. However, when disaster strikes, we are helpful, compassionate neighbors, each pitching in to face hardship together. It was our team's goal to help encourage this second behavior pattern all the time.
Yes, the team, but wait. Leaf peepers? I recently returned from vacation in Vermont, where Luigi assumed I'd be photographing leaves. Nevermind.
Our juggernaut of raw, unstoppable productive force consisted of Luigi, Caitlin, Casey and myself, covering nearly every discipline represented in the Labs from design to research to front-end and back-end web development. With this veritable cornucopia of skills, we knew we had to bite off something significant.
Getting to work
Despite high confidence in our ability to execute, we were pretty strapped for ideas until late afternoon on the Friday before go time. We had been toying with a voice and SMS interface to guide people in rural areas without broadband internet toward the local public services they need, but Casey discovered in preliminary research that the infrastructure to make such an app worthwhile really wasn't there. We'd already scrapped some decidedly lesser ideas, such as a kitchen cleanliness tracker (pfff!), an rfid/motion sensor combo that played WWE-style entrance music for every Sunlighter as they came into the office each morning, and 'Auto-Tune the Law,' which would have set Sunlight Live to music, pitch-shifting testimony a la T-Pain, which (sadly!) didn't appear to fit the timeline or budget.
So, after reaching consensus--and without a comfortable degree of consideration of our problem domain--we got cracking Monday morning. The plan was to use a plain old Rails/ActiveRecord/Postgres stack to deliver the web interface, and Twilio for SMS and voice. Casey took our basic concept of 'have' and 'need' and set forth on IA and taxonomy, while Caitlin began on a color palette and logo. Luigi dug into the Twilio API, and I spun our project up on Heroku and started modeling.
Good teamwork is everything when dealing with compressed timelines, and we did our best to keep in touch throughout the process. We set up an IRC channel on Freenode that we hung out in each day for answering quick questions, and escalated to face-to-face as needed. Heroku provides an IRC bot to notify the room of deployments, which came in handy for status tracking and letting team members know when to update their code. For copy and user stories, we worked with an EtherPad instance that Eric had stood up for everyone to use, and found it to be great for collaborative typing.
With the lofty goal of a backend, 3 interfaces and loads of location-aware goodies in just a couple of days, we had our work cut out for us. As mentioned above we decided to let Rails and Twilio handle the interfaces, and even though I tend to prefer Python/Django, it felt good to have a chance to play with some of the less-familiar-to-me-bits of Rails such as single-table inheritance for 'needs' and 'haves,' and scoped/nested routing patterns that are new-ish in rails 3. For IP-to-location, geocoding and radius search I used GeoKit, which was a pleasure to work with, though initially it forced me to trade sqlite in development for postgres.
For the SMS and Voice features, Luigi evaluated Twilio and Tropo. Both are excellent telephony systems, with straightforward RESTful APIs. But Luigi figured out how to get a custom phone number through Twilio first (719-522-NICE), and so that's what he chose. When working with telephony systems, outgoing activity is straightforward: make an API call. But how does one handle incoming activity? Twilio expects developers to implement endpoints in their app using a custom XML-based markup language, TwiML, while Tropo allows developers to host scripts on Tropo's cloud. Tropo also supports an endpoint-based solution, similar to Twilio. On top of all that, Tropo offers a new service called SMSified that makes development even more straightforward if one only needs to support SMS.
By the end of Monday, we had a solid start--Catilin had a great logo that pulled inspiration from the letters 'NN' back-to-back to form a Mr. Rogers-esque cardigan, we had hello world in SMS, an admin scaffold, an auth system, some models and a sense for how requests and offers would be delegated. But to poorly paraphrase Bret Michaels, every Monday has its Tuesday. While working with Caitlin to help her get started integrating her markup/css into the project, Luigi mistakenly deleted all of her work! The next several hours were spent attempting to reconstruct it from browser cache, which turned out reasonably successful, though very costly in time.
To add illness to insult and injury, Caitlin came down with food poisoning that night, leaving your Leaf Peepers woefully short-handed during Wednesday's pretend-like-you're-working-but-try-to-make-up-for-lost-time sprint to the finish.
For fun, if not profit
By our measure, we didn't quite make minimum viable product, but the fruits of our effort stand nonetheless at http://niceneighbor.net, with code at github. We stand by the idea and perhaps will develop it further at some point to get it over that elusive hump of 'usefulness.' Results aside, we had a great time working together and learning about bits of tech we don't normally use.