 Hello, thank you for coming. Today I'm gonna share the story of how the team at Betterment secretly swapped out the entire front end for several of our apps last year in order to launch our new brand identity. So my name is Chris LaFresto. I lead front end architecture at Betterment and I love helping engineering and design teams find ways to work better together. I play some non-computer keyboards and you can find me at Chris LaFresto on GitHub or Twitter. The last year, Betterment spent six months creating a new brand identity. This meant reimagining the company's mission statement, photography style, logo, color palette, the entire user interface of our web and mobile apps, online calculators, emails, everything had to change. So from start to launch, the entire project took six months. It was the last two month stretch when we built everything. Now this is an aggressive timeline. We did it to ourselves. The agency said expect at least 12 months for the brand exercise. So we said, how about half? How about half that? We could aim for Betterment's birthday. It'll be at the end of May, that'll be great. It'll be after tax season so no one will freak out if their tax form suddenly looked different. It'll be before the summer because nobody reads press releases from the beach. Whereas it happens, we delay it a little bit. So in March, this is what our homepage looked like. But by May, we wanted to snazz it up. New colors, photography, new content throughout all of Betterment.com. We wanted to apply this brand to our retail app. So this is what our summary page looked like in March. But May, we wanted new navigation, that new word mark in the top. Everything's tighter because it's on a grid system. Now, investing involves risk. Past performance does not guarantee future results. But it does look like this user's about to have a really good two months. So we got that going for us. This is what our portfolio page looked like. Basically the project requirements where you see that over there? Yeah, can't look like that anymore. So if this seems wildly impractical, buckle up. Our mission is to redesign everything in eight weeks in secret. We want this timed big reveal. All of our apps change at once. Articles appear online. And then we'll just bask in the beauty of our brand new brand. Then we thought, well, since we already have to touch everything anyway, while we're in the neighborhood, what if we made everything responsive? You know, it never was the crisis. So what are we talking about here? So these designs were never gonna work at these small sizes. It was going to take a lot of work to get from that to this. Reconstruct all our CSS, all our HTML by May. So you're probably thinking, this is gonna be fine. We'll just whip out our trusty feature flag framework, design system and get to work. So at this point, it is helpful if you already have one of each, which we do. If you don't, no worries. Hopefully this story peaks your interest. Now big projects are risky in part because they change a lot of code. One of the best ways to cope with this risk is by slicing your work up into tiny pieces and shipping them one at a time. Now this means shipping incomplete work. So that's okay. You wait until it's ready. You hide it behind a feature flag. And once it is ready, flip a switch and turn it off. Now a huge advantage of this approach is that you can solve problems one at a time when they pop up. You can see what's working, what's not changed your mind about things and you're not jerking your users around as you figure all of this out. But a rebrand is so big, it touches everything. Like how do you put everything behind a feature flag? So at first we didn't know how, but our engineering principles dictated that we had to find a way. The only way to have a worry-free launch day was to not ship any code on that day. Instead, we'd have to get to a point you're happy with, flip a switch and turn it on. So Better Mint's feature flag framework is called Test Track. It follows visitors and users across devices. We have clients for Rails and JavaScript and all our mobile apps. And we use it all the time to run experiments and dark deploy features. If you don't yet use feature toggles in your workflow, you should definitely consider it. It'll change your life. There's a few gems out there that make it really easy to get going, some really great services out there. But slicing of work doesn't do much good if each slice ruins the last one, which is often the case when CSS is involved. So for this project especially, we needed to assemble new interfaces on the fly across multiple apps, see what worked, see what didn't. And the best way, or really the only way to do this efficiently and creatively, is with a component-oriented design system, which would give us reusable components. Now Better Mint's design system is called Style Closet. It lets us share patterns and components, evoke Better Mint's look and feel across all of our apps. Now if you don't have a design system, don't worry. We had to rewrite ours entirely as part of this project. But the important thing to remember is that both Test Track and Style Closet were already integrated in all of our apps. So otherwise, no way that this eight-week project timeline would have been remotely possible. Like investing in our systems over the years had put us in a good position such that what once would have been deemed wildly impractical actually became the basis of our project plan. But we didn't know what that meant at the beginning of the project. We were just wondering, how in the world are we going to do this? Like forget Gantt charts and press releases. We just need a halfway believable way to get this out the door. How can we get from here to there at all? To which the engineers say, I don't know. But also spike, just do something. It doesn't matter if your prototype is dumb as long as it's concretely dumb. This is why I like to ask myself, what's the dumbest thing that could possibly work? Well, here we go. We already ship a design system into each app. So I thought, what if we create a rebranded version of the design system? Then each app already has a SAS manifest. What if we made a second one? We used the rebranded system behind a feature flag. And then finally, we know that the new responsive designs need different markup. So what if we had some view logic that understands the feature flag and knows how to keep our world separate? The stuff that's in production and all the new rebrand stuff. That seems reasonable enough. So we got to work. I spent about one minute writing the beautiful rebrand CSS that you see here. I wanted something garish, so I figured white on blue ought to do. And I wrote some JavaScript autogly styles on in our design system doc site. So with the old styles, the typography demo looked like this. But with the new vastly improved styles, it looked like this. So it was at this point, I mean totally nailed it, right? So at this point, I started going up to designers one by one, telling them I had started the rebrand project so they'd get really excited and ask to see it. And then I would show them it. And it looks on their faces, varied. But we had what we needed. We had a way to do new style stuff without messing up our old style stuff. And we shipped this to production. We actually cut a minor version release of style closet. And I met the next step was to try to get this dumb stuff into an app behind the feature flag. So I upgraded retail to the latest version of style closet, made a new rebrand SAS manifest that pulled in the rebranded system. And this is what we wanted to put behind our feature flag. So in our application layout, we added logic to use the new style sheet if this test track feature flag rebrand enabled was on. Now in public, no one's gonna see this nonsense. This feature flag is initially off for all of the users. But engineers working on the project or anyone else keeping tabs can use our test track Chrome extension to flip rebrand enabled to true and get the new styles. And we shipped this to production on day one of the project. On launch day, all we had to do was log into our test track admin site and flip this rebrand enabled flag to true for everybody to go live with the new brand. Now our designers being a serious bunch already made me make my colors mildly less ridiculous. But things are holding together so far. So for our last trailblazing trick, we're gonna juggle old and new markup at the same time. I ported the CSS for a few of our cleaner more modern components, the header and progress bar and footer that you see here. They set about making the demo page work for both the old and the new worlds. That's when things started to get a little weird right away. We had CSS selectors that referenced colors, the colors had changed. So we already needed to view logic for a pretty silly reason. And there are much bigger markup changes coming. Starting with this SVG logo and the grid system, but getting hacky and hand wavy, things are holding together pretty well so far. So we decided to push ahead and see if this would work in a real world situation. And an hour later, we had an answer. It did not. Even on the simple pages, I mean like most Rails apps, we used layouts to share, page structure and parcels to share, chunks of markup. So even to hack this far, we needed a lot of logic in a lot of places. And so far, this was just a reskin. The actual redesigns, we're gonna rearrange all of this content. So I found myself gazing at this ginormous SVG. No longer so sure we'd be able to share one set of markup. Let's recap. We wanted the ship, a rebranded design system, and we did it. Lots of work to do, but we're off to the races. We wanted to use this new design system in our apps behind a feature flag. And we did it. Oh, you already knew that. But as for the view logic necessary to set up the new brand, nope, way too complicated. Not gonna work. But the good news is we're transitioning out of that terrifying feeling at the start of a project when all we know is there's a bunch of things we don't know. Followed by a bunch more things we don't know we don't know. This pile of unknown is best faced head on. We strike out, plays a trail. We'll make sure one way or another we can get from wherever we are to wherever we need to be. So we have our styles worked out, but the tangled view logic showed us that what we really need is a separate view layer for this feature flag. Because all of our problems will go away if we can just add rebranded versions of views without touching the existing ones and have a bit of logic that just determines which one to show. Now this is a specific requirement for which Rails has a pretty great answer built right in. Action pack variants. So whether you realize it or not, like we're all familiar with the Rails template resolver. When a controller is rendering a request, it's the resolver that knows where to find the right view on the file system. So that's controller path slash show dot html erb. What I didn't know was that after that html format, the resolver checks for an optional variant that you can define. So let's say that you have a website that serves colorful high res pictures of robots. But you're looking at your logs one day and suddenly realize that you have a lot of traffic from experimental Kindle browsers that can't see color. So you decide to optimize the images for their black and white existence. Oh man, here we go. So the controller can do a browser check and say hey, there's a Kindle making this request. I'm gonna set request dot variant equals Kindle. And that'll make the resolver first look for a Kindle template. If it doesn't find it, it will fall back to the plain html erb. It's been serving the rest of us all along. This is built right into Rails. So luckily when I said out loud, what we really need is a separate view layer for this feature flag. The coworker of mine, matter of fact, they replied, well, we can use a variant. All we had to do was move this rebrand enabled check from our application controller, our application layout into our application controller. It's a few lines of code and we were in business. We realized we wouldn't have to make changes to the existing views for the entire project. And even better, we could just delete them after we launched their replacements. We were excited. It was additive and therefore completely safe to just make new rebranded versions of everything. We couldn't break anything, even if we tried. Challenge accepted. Obviously we could. Obviously we did. But our bugs ended up being real bugs pertaining to real features, not project config gotchas. So our focus shifted to all the stuff that needed changing. We audited our design system, all of our apps, and came up with a long list of pages and components that needed to either be reworked or rebuilt entirely. As we thought about how long it would all take, something had to give. So style closet began life as a way to share patterns across our apps. But it was tough going. The apps weren't built with this system in mind. Our components never just worked when you dropped them in. There's always a fight. Our apps all had these complicated CSS code bases that few braved, even fewer loved. I actually included Captain Sully Sellenberger on this slide to assure us it's gonna all be okay. But the fact of the matter is as this peer reviewed, totally factual study indicates CSS is hard. It gets harder as the team grows. It gets harder as the code base grows. And our old system suffered all of the usual pitfalls. CSS is globally scoped. You introduce a new thing, something else breaks. So we'd compensate by scoping our rules more strictly in a show of strength. That doesn't stop anyone else from making their change more important than yours. But then perhaps most insidious is that in reality, you have to use these so-called reusable components at your own risk. Now swapping out our entire view layer represented an opportunity to start fresh with a new CSS architecture. And so we decided to rewrite our design system. This isn't out of the blue. We've been working towards this. We had internal prototypes, drew inspiration from all manner of open source projects and untold numbers of medium articles. We were confident enough to make a leap because we felt we'd be able to move faster with a new system than continue to fight the old one. So we put together a wish list. Sensible defaults. Wanted zero config for an app to get going with the system. Default element styles, so that semantic markup automatically looked good. We wanted cohesive systems for spacing, typography, grid, breakpoints, color, as well as the ability to apply these system styles consistently in either SAS or with utility classes in our markup. And finally, a suit CSS naming convention. It's like BEM so that our components could defend against inward and outward bleed to achieve true reuse. So let's dive in. We built a lot. We're gonna move through overly quickly. We created an exponential spacing scale with increments that are all multiples of four, used it to create spatial relationships within our components throughout all of our layouts, every space you perceive. So you could apply a padding using this SC spacing function, which was using a unit tested SAS function. If you're assembling page markup in an app, we provided corresponding utility classes built with those same SAS functions. So to apply the same padding, you could use a utility class selector without needing to write CSS in the app. We had a new color palette, so we made a conventional naming scheme. So we had functional access in SAS. We created color and background color utility classes. We had five primary colors, four secondary variants of each. And then for betterment's complex data visualizations, we created a gradient system with 100 color stops for each primary color. Our previous responsive efforts used an ad hoc set of max-width media queries. So we took the opportunity to research and standardize on a much simpler set of min-width media queries. Now, constraining this breakpoint set allowed us to create responsive versions of each utility class. So it's easy to specify a default padding and then loosen it for larger viewports and still not have to write additional CSS in the app. We created a linear scale of typography sizes based on the spacing scale. We had font size line height combinations optimized for our new font. And then we'd adjust line heights and some header font sizes responsibly. In keeping with our goal for semantic markup, looking good by default, we created a vertical rhythm system applied as bottom margins to typographic elements. Again, based on the spacing scale, adjusted responsibly. We built a 12 column grid based on Flexbox. We had fixed width gutters based on the spacing scale, adjusted responsibly. Inspired by the Dropbox paper team, we designed a new icon set in Sketch on conventional artboards. We wrote a script that uses Sketch tool to export SVG files, optimize them, generate view parcels, and a corresponding Rails helper. So designers can now change or add icons by updating Sketch and just opening a pull request. Engineers can pop them on a page using this SC icon helper. And then we recently made this interactive icon builder in our design system docs site so that engineers can generate the ERB for the icon they're looking for. We built all the traditional components, design system classics like card and button. For the first time though, these components were truly reusable. We could put them in anywhere and they would work thanks to our suit CSS naming conventions. If we could drop them in, they'd all play nicely with each other. We also built layout components with built in content slots. And these components served a dual purpose. It made it easy for our team to start building responsive pages because they did all the heavy lifting, taking stacked content slots and then putting them on the grid at larger viewport sizes. But they also served as examples for our teams for how to build these components with our new patterns. And we built visualization tools so that you could see the underlying content slots and grid. These are actually all browser screenshots of betterment.com, visualized with our style closet Chrome extension. And as we built each new piece, we used the visualization tools to check our work. So suffice it to say, an action-packed productive few weeks with unprecedented levels of collaboration between our engineering and design teams. Like for the first time, we had designs expressed by a system built with the system. And then as teams began to use the system, we immediately noticed a step change in the pace of our UI development. Pages that used to take a day would spring to life in about an hour. Engineers ended their demos saying, I didn't write any CSS and it's responsive. Now I don't want to paint too rosy of a picture. There was a learning curve, there was a lot of work, but at this point, we knew we had made all the right strategic choices. So the only remaining question was, can we hit our deadline? When can we launch the new brand to the world and return to our regularly scheduled program? Now a fixed date and a fixed scope are not a winning combination. We were stressed because we didn't seem to have a way to punt on anything. Like a brand isn't something you can turn part way on. We needed all of our pages to be in on the action. We had two levers we could pull, the date or the scope. We didn't want to shift the date or we didn't know how to shift the scope, so we were stuck. So maybe just to lift our spirits, we looked at everything we'd already done. We had used view variants to great effect. We now had this secret rebrand mode that internal employees were testing behind the feature flag. And then while reliving the insight that led to this, we had this moment of clarity or deja vu, or I don't know, it may have been amnesia. We just did the exact same thing again and made a lighter weight reskin mode. So with just a few tweaks to our variant logic, we wired up a switch that teams could flip on to reskin a page. So with a single line of code, you'd get a new variant, which meant new colors, new fonts, and some breathing room. It wasn't gonna be the end of the world if a page or a section wasn't quite done by the launch deadline. We could get on-brand enough in the meantime without having to completely solve every last technical problem. And it yielded surprisingly good results. We even chose to leave some of the deprecated systems reskinned permanently until their ultimate demise and deletion from our code base. But most importantly, we had decoupled done from launch. Constraint really is a wonderful thing. So we were debriefing after the launch and kind of pondering how we would have arrived at these results with our normal iterative processes. And we're not sure that we would have. We definitely not as creatively and efficiently. We shipped more code full of better ideas more quickly than we thought possible. And we eliminated far more debt than we created. Some of us, well, we were so relaxed when we saw, okay, not only did we hit our birthday launch date, but we were so relaxed on that day. And some of us may or may not have been sound asleep when we flipped that feature flag on. Constraints improved our plan and improved our results quantifiably. So there's many, many reasons to be careful when intensifying effort around project deadlines. By definition, you're subverting the notion of sustainable development phase. And it's a fantastic way to turn working software into buggy software. So we analyzed pull requests that's during and after the project. Now, because we're doubling down on the design system, the style closet repository, saw the most dramatic spike. There's 247 pull requests. Now, for a perspective, this represented 49% of style closet pull requests ever. But that first half had been spread over two and a half years, not 54 days. We shipped 44 releases of style closet, which means we were releasing every workday. Then we launched and we're immediately back to normal. So at the very least, even accounting for recoil and recuperation, there reflects a lack of panicky showstopping bugs. With Betterment.com, you kind of see a column before the storm. We knew all of the content was on its way out the door. Then you see this huge spike, because we built an entire new WordPress theme with our new design system. And we turned it on on launch day. And again, immediately back to normal. Now our retail app is part of a repository that contains other apps. So it's not as clear of a signal here. There's a delayed spike, partially because we were waiting for the design system, partially because there was a bit of a rush to aim for that deadline. But then we're immediately below normal. So we told ourselves it's probably easier to work in the new world, although it was now summer. But we were thrilled. This is what we had hoped to see. Now let's take a look at all the CSS that we wrote. The CSS rules are assigned a numeric specificity, highest score wins, in the case of a tie, last one wins. So Harry Roberts of CSS wizardry, came up with this sort of experimental notion of a specificity graph. On the X axis, you plot rules based on their order in the cascade. On the Y axis, you plot their specificity. And he mused, loosely speaking, this line should be smooth and trend upward. Because if you write a dodgy rule, some poor unfortunate rule that comes after it will have to fight back. And that'll show up as a jagged graph indicating developer pain. So on the left, we have style closet one, some of our better CSS, not great, not bad. On the right, we have style closet two. It's much better, smoother and it's a much lower specificity. But it's really fun to see and explain the graph features. You kind of see our CSS reset, then it's flat. That first bump is actually a visualization tool, flat. Then we see this tangle of some old form styles that we didn't have time to rewrite. And then at the end, you see a bunch of our utility classes. These are important by design so that our apps can freely use them in their markup. But this same analysis is so much cooler in retail. So on the left is the old CSS that was no fun to work with. On the right, wait a second, that's almost entirely style closet. The in-app CSS is basically all the way over on the right. The system to app ratio is fantastic. It means dramatically less work in the app to build the features with the new system. So that's quality. Let's look at quantity. Way, way, way down. Retail's CSS code base went from about 10,000 lines down to about 2,000 lines. That's on par with what we saw at betterment.com. The old WordPress theme, about 12,000 lines of CSS. The new one, about 2,000 lines of code. Now remember, we're not just matching functionality. The new code base supports dramatically improved user experience, responsive. And it adds all of these components that made it possible to build all of our application interfaces up from scratch as quickly as we did. Well, let's look at the payload size. In a nutshell, more system, way less at the app level. The design system payload went up about 57%, GZipped from 23 to 36K. But if you look at what retail is shipping across the wire, it dropped by 54%. 86K down to 40K GZipped. Now this is far less CSS from a far more capable system. And we actually have experimental style closet three builds that are weighing in around 24K. So we're back down to the original payload size. So with all of that behind us, what are we doing with our new found leisure time? Well, standardizing the view patterns across all our apps freed up a lot of time and creative energy for a bunch of new stuff. Reintegrated webpack pipelines into all of our apps. Then we've since built a Rails component framework inspired by JavaScript frameworks. It establishes a clean foundation for a hybrid front-end architecture in which Rails stimulus and react each play a part. And we're building form interactions, animation frameworks, data visualizations and lots of features. All based on the system we launched last year, which has been improving by the day. So I was listening to a James Corden interview and he relayed something that his dad used to say. That the difference between doing something and not doing something is doing something. We accomplished impractical things in a seemingly impossible time frame all because we made a decision to just do something, to commit to shipping and to commit to finding clever compromises in order to do so. The stories I've shared involve dozens of people who are eight action packed stressful weeks, problems and changes, mistakes and inventions, distractions and debates. We didn't lose our cool, we actually had a lot of fun because nothing really beats tackling tricky problems with good people. Thank you.