 Before we start, I have a question. Do you like road trips? I hope the answer is yes. If you do, what do you think makes a road trip successful? While you're thinking about it, let me invite you to take a journey with me. Along the way, we'll make a few stops to check if our foundation is well-equipped for the adventure. We'll wake up in Moscow, speak different languages, sandboat in Colorado and drive through a pandemic. All that to find an answer to the question. What does it really take to launch an enterprise product at scale during the COVID-19 pandemic? Here's our destination. We are building from scratch enterprise sales software for LinkedIn, a place where sales leaders can uncover new opportunities and develop a better sales strategy by leveraging the LinkedIn economic graph, the digital representation of the global economy. We'll welcome our users with a single sign-on and offer multiple licenses as a starter. Our main Ember UI menu will include external dependencies, multi-dimensional taxonomies, custom personas, interactive charts, and so much more. But this is where we start. 2019, the year I joined LinkedIn. Back then we had a massive UI team, two UI engineers, and I was the second one. No, I had no prior Ember experience. There's one thing you should know about me. I'm addicted to adventures. While working in tech for more than eight years, I tried on different heads, worked in both the front and back yards of engineering. I already invaded worlds of video games, ads, car racing, freight shipping, investment on cryptocurrency. So growing a complex enterprise product on unknown to me Ember soil was an adventure I couldn't miss. I knew it would involve new challenges and I was right. Let's take a closer look. Like any other product, we have must-haves like graceful degradation, AB testing, et cetera. But on top of that, we need to account for enterprise specific processes and challenges that come with KL. Every feature we build has to consider multiple microservices, external dependencies, sign-offs from other teams, et cetera. All that combined makes the final list of requirements quite overwhelming. And you're probably thinking, that's why enterprise development is slow. I know, I've heard this many times. And while it is true that we can't afford to move fast and break things, we can't afford inaction either. That's why our approach follows the core principle of stability without stagnation. As a team, we decided to invest heavily in the foundation, automate and reuse as much as we can. As brilliant as this sounds, the implementation of this principle wasn't always straightforward. It wasn't a straight line nor a curve. For me, it was a journey. The journey through two intertwined roads, personal and professional, where lessons from one echoed into the other. Maybe they aren't so different after all. Let's find out this by driving to our first checkpoint, St. Petersburg. My friend and I planned a trip to Moscow. We discussed the plan, agreed on the dates. But out of sudden, he showed up a week early wondering why I still wasn't ready. Shocked, I quickly packed my bag and one hour later, we were on our way to Moscow. It ended up to be a very fun trip. Although later, he confessed that it was a prank that turned into a real adventure only because I accepted it. I wish all unexpected changes to our plans ended so well. Unfortunately, that's not the case, especially in the world of UI and API agreements. How it usually happens. The UI and API team signed an API contract by defining a schema. UI kick-offs local development using mocked endpoints in Ember-Selai Mirage. Then API developer introduces some changes. UI engineering might be not aware of these updates, so they continue to build the UI with outdated assumptions. The discrepancy can cause bad regressions. This problem is what makes validation one of the crucial components of client-server interaction. Our solution to this problem isn't open source, but I'll explain the overall idea that you can apply to your own Mirage setup in Ember. Let's look at the schema. In green are the typical components of Mirage workflow. The key difference is in serialization process. Each mocked endpoint is mapped to corresponding API schema. Schemas are treated as dependency packages. To upgrade API version of your local mocks, you just need to change the package version. Then custom Mirage serializer comes into play. It takes those schemas from your repo, validates each requested query program, and generates mock data, but only for the fields defined in that schema. If you try to check the system by introducing custom fields in Mirage Factory, it will throw an error. This solution proved to be effective in surfacing missing required purposes, declining outdated request programs, and preventing any schema pranks. Now let's jump back to our engineering car. We are going to Colorado to perform our first accessibility audit. I promise no more secrets. All these other technologies I'll be mentioning are open source. San Dunes National Park, Sandboarding Paradise. I always loved the idea of sandboarding. I've heard it was similar to snowboarding, so I got excited and went all in without any further research. Long story short, it was a disaster. Unlike snow, sand demands waxing every few meters. Instead of shredding the sand, I spent the most of my time waxing the board and blaming myself for not doing proper research. Concedently, that was also the time where our first accessibility audit was taking place. One thing to keep in mind, accessibility support isn't the choice for us. It's a must have requirement. However, since our product wasn't released globally yet and we had other priorities, by the time we performed our first accessibility audit, we already had an impressive amount of features. Still, I wasn't too concerned about it. On the contrary, it was a new experience and I was excited about accessibility audit process in general. So here I am, exhausted of the long dangers looking at the result of the accessibility audit. 100. The team reported close to 100 issues. I experienced the backslash. For the second time a day, the universe was telling me that unrealistic optimism can be very painful. 30% of those issues could have been easily avoided. How? By leveraging and for accessibility testing. It's easy to adapt and straightforward to use. Built on top of X-Core, it gives you access to all the rules and options. My personal favorite bonus of this library are error messages. Not only do they tell you what went wrong, but also why it went wrong and how to fix the problem. So don't neglect easy wins, please. Do your research before shredding the sand. My next story is about dangerous regressions. Once upon a time, I decided to try work and travel program. Our goal was to build a floating staircase. Yes, we did it, but that's not what this story is about. It's about how the entire innovation project has started. Apparently, the owner of this house didn't like one of the walls in his living room. So he removed it. Yeah, that was a load bearing wall. So he put the entire construction of the house at risk. Coming back to our UI world, we can consider page markup as one of the load bearing walls of front-end construction. Uncontrolled CSS changes aren't threatening web existence, but can easily damage visual integrity and endanger overall user experience. In projects like ours, with hundreds of components, the only way to prevent visual regressions is to use automated testing. After evaluating existing solutions like Percent Phantom, we adopted Ember Backstop. It's a visual test helper that generates and compares screenshots with a reference from baseline commit. You'll also need to consider other aspects like freezing log data, but let's save these topics for the future. What we'll focus instead is how can be leveraged the same exact setup for localization. As of now, we support seven languages. Localization is a multi-step process that involves collaboration between multiple teams. Verification is one of the steps. We need to ensure that all our components look as intended in all supported languages. How can we do that? Screenshots. Indeed, if you can generate screenshots for one language, why can't you do it for another six? By triggering your test for different language, you can use the same exact backstop assertions but in reference-only mode. The result? One tool that covers two requirements. Okay, that was a lot of information. Let's make a pit stop. We established trust in client-server communication and performed accessibility audit. Introduced visual regression and localization. On the background, our team covered all other requirements and even other accessibility bugs. By investing in strong tech foundation, automation, and creativity, we achieved stability without stagnation. Our team was moving full speed, preparing for global launch. Then the world turned upside down. Along with drastic changes that came to our day-to-day lives with remote work, we started seeing decline in engagement from customers. Roadmap items no longer seemed relevant. Third of our engineering bandwidth was borrowed by another team. The launch was postponed. All that endangered our team culture, which we cherish a lot. LPMs tirelessly worked on uplifting team morale. We had virtual happy hours, watched zombie movies, cooked meatballs, played trivia, and even cross-seached. Nonetheless, life wasn't the same. Day by day, I was submitting less and less code. Box will start crawling over from all over, and I fell into a sale-blame trap and developing pasta syndrome. Longer working hours didn't help. Hiking, grinding, even closed apple rings. Nothing was working. And then I asked myself, in the engineering world, what do we usually do when we hit barriers in development? Right, we apply problem-solving strategies, one of which is root cause analysis. So I cleared my wild board and started brainstorming. List of problems and never-ending chain of why questions uncovered that even though I used the right tools, I was finding side effects, ignoring the core issue. Denial. I denied importance of the crisis. Tried to prove that we can recreate almost anything as long as we have enough of willpower and perseverance. This is an airstream from Milwaukee, four miles away from my apartment. At that time, campings were closed, so I rented it to recreate camping experience. But even with the wildest imagination, that airstream couldn't leave the backyard and know it wasn't camping. Few days later, I came back disappointed. It's still an original and unique experience, you might think, and you're absolutely right. You see, I couldn't appreciate that airstream for what it was, because I had an inadequate set of expectations, because I was applying the right tools to the wrong problem. The same way I was boosting my work performance while ignoring the most important questions. Did I still want to invest my life in this product, knowing it might never be released? What was my definition of a successful journey? To answer these questions, I came back to my fundamental engineering values. I love using technology as a tool for solving challenging real life problems with like-minded people who share the same passion. So for me, success was an intersection of those three pillars. And I had all three of them. No, I couldn't guarantee a prosperous future for our product, but I knew what I could do to increase the chances. Investing in the resilient technical foundation, contributing to the integrity of our team culture and putting our members first. This realization helped me to reestablish my engineering purpose. Luckily for us, soon after that, we started seeing the rise of virtual selling. Increased demand in high quality data and insights put our product at spotlight for many prospect customers. We entered a new life cycle, double downed on our roadmap. We had to act fast. And that is where our previous investment in foundation, localization tools, accessibility, testing, et cetera, really paid off. Last month, we launched sales inside globally. Wow, what an adventure we had here. Thank you for trusting me as the driver and thank you for sharing your precious time with me. I wish you all to have many, many insightful journeys. Cheers.