I presented at the NYC Contentful Meetup about how we re-built our website at DoSomething.org, and some of the lessons we learned along the way.
Like many organizations, we had an aging monolithic application that was resistant to change. We wanted to burn it all down and rewrite it from scratch, but we accepted that was probably a bad idea.
Instead, we used the Strangler Pattern to slowly extract & rebuild - moving our chatbot into an event-driven Node.js application, our user & activity data into Laravel REST APIs, and our content into Contentful.
This allowed us to tackle our overwhelming technical debt in manageable chunks, completely rebuilding a complex monolith – over five years! – without stopping feature development.
Our old content management system had a strict "one size fits all" schema, which stifled our editors' creativity & made it difficult to quickly respond to current events. In order to build a flexible toolkit for social change, we architected our new website around the concept of pages and blocks.
Blocks are user interface elements that can be arranged to make page layouts. We used an adaptor component,
ContentfulEntry, that read JSON from our CMS & translated it into the relevant React interface component.
This also allowed us to iterate quickly, adding new site-wide or one-off functionality without needing to adjust our underlying page schema.
While moving quickly, we needed a way to measure the impact of our changes. We use Sixpack, an open-source A/B testing tool from the team at Seatgeek. Sixpack allows us to run experiments in our codebase, comparing the effectiveness of one interface to another.
We also created an
SixpackExperiment block in our content management system, allowing editors to create their own self-service experiments to test different content and blocks.
Development doesn't stop after shipping 1.0. We're continuing to evolve our website and development practices. We use the Contentful Migration CLI to evolve our content models (and content itself) using scripts, and are using GraphQL to optimize our queries to these newly decoupled services.