ExpressConnect
Built ExpressUI, a design system from scratch, and redesigned Service Express's equipment management portal on top of it, replacing four years of UI drift with one component library.

The short version
ExpressConnect is the portal Service Express customers use to manage their data center equipment and service requests. Version one was built in 2018 by an outside software firm on a hard deadline, and it showed. No component library, no shared design language. Four years of features each drifted a little further from the last. Over ten months I audited the whole product, moved design from Sketch to Figma, built ExpressUI (a design system from scratch), and redesigned the portal on top of it. Handoff went from arguing about spacing to picking variants.

Where the drift came from
Nobody made the portal inconsistent on purpose. The 2018 build shipped on time, and design took a back seat to the deadline. After that, every developer adding a feature made their own calls on spacing, color, and layout. Reasonable calls, mostly. But four years of them, each pulling a slightly different direction, adds up. The portal worked. It just didn't feel like one product.
The audit
Before proposing anything, I wanted to know exactly how bad it was.
I screenshotted every screen in the portal and tiled them into one Figma page, grouped by pattern. Then I counted. Fourteen button styles. Six grays so close together I had to overlay them to tell them apart. The tables were worse: three unrelated patterns, each with its own idea of how sorting should look. It took the better part of two weeks and most of it was numbing. But the tedium was the point. By the end I knew the portal better than the people who built it.
The audit also surfaced things interviews never would have. Users had built workarounds into the gaps: browser bookmarks pointing deep into the portal because the navigation didn't surface the pages they actually needed, and at least one customer keeping their own spreadsheet of service request history because the portal offered no way to see trends. Every one of those workarounds was a feature request. Nobody filed a ticket, they just built the thing themselves.

Who was actually using it
I interviewed the different user groups and built personas to map their daily workflows. The pattern showed up fast.
Different roles needed genuinely different things. Each group worked in its own way day to day, but the portal handed everyone the same generic screens. The personas gave us a way to argue about priorities with real people in mind instead of "the user."

The daily operator
In the portal every day filing and tracking service requests. Knew every quirk and had a workaround for each one. Wanted speed, not features.
"I know where everything is, but only because I had to learn it the hard way."
The occasional checker
Logged in a few times a month to check on equipment status. Got lost every time because the navigation assumed you were in it every day.
"I end up calling support to find things the portal supposedly does."
The reporter
Needed rollups and trends to justify the contract internally. The portal offered raw lists, so the reporting happened in spreadsheets outside it.
"Every quarter I rebuild the same report by hand."
The port that went nowhere
The move to Figma was already planned. My original pitch was the fast path: import the Sketch library, clean it up, keep moving.
That plan lasted about two weeks. The Sketch files came across as a pile of broken overrides, detached symbols, and duplicates with names like "button copy 4" sitting next to "Button FINAL." There were no naming conventions to preserve because there were no naming conventions. I spent a few extra days telling myself the next batch of symbols would be cleaner than the last. They weren't. By the second week I realized I was spending more time untangling old symbols than it would take to rebuild them, and the rebuilt versions would actually be structured correctly.
Calling it was uncomfortable, mostly because the port had been my idea. But porting the mess would have recreated the same problems in a nicer tool. We scrapped the import and started clean.

Sequencing the work
The rebuild decision created a scheduling problem. The portal redesign and the design system both needed the same months, and product understandably wanted visible portal progress, not a quarter of invisible foundation work. We considered three ways to sequence it:
Portal first
Redesign the screens now, extract a system from them later. Fastest visible progress, but this is exactly how v1 drifted. Every screen becomes a one-off and the extraction never actually happens.
System first
Build the complete library, then redesign on top of it. Cleanest on paper. In practice it meant months of components designed in a vacuum with nothing shipping, and guessing at what the redesign would need.
One workflow at a time
The winner. Redesign one real workflow, build only the components it needs, then promote those into the library. The system grows out of real screens instead of hypothetical ones, and the portal visibly improves the whole time.
The third option meant the early library was heavy on tables and forms, because that is what the first workflows needed. I was fine with that. A component that exists because a real screen demanded it beats a complete set built on guesses.
Building ExpressUI
We built ExpressUI as a full design system in Figma: atomic components with proper tokens and variants. Buttons, inputs, cards, tables, and navigation elements, each rebuilt from the ground up rather than rescued from Sketch. We also moved off the generic Material Design palette the old portal leaned on and chose colors and typography that matched the Service Express brand. The portal finally looked like a Service Express product instead of a Material demo.


The token argument
The first token review with engineering did not go well. I brought semantic names: text-primary, surface-raised, border-subtle. The lead front-end developer wanted to keep the variable names already in the codebase, things like $se-blue and $light-gray-2, because renaming meant touching hundreds of files for zero visible benefit. We went in circles for most of a meeting until I asked which variable a developer should reach for on a disabled link. He named three candidates. That was the argument, made better than I'd been making it.
The resolution was an alias layer. The semantic tokens became the public vocabulary, mapped onto the existing variables underneath, so nothing had to be renamed on day one and the old names could be retired gradually. Not the purist version of a token system. But it shipped, and both sides could point at the same name and mean the same thing, which was the entire goal.
Redesigning the portal
With ExpressUI in place, we redesigned the portal workflow by workflow. The layout got cleaner and the data-heavy screens (which is most of them, this is equipment management) became genuinely readable. For the first time you couldn't tell which screens were new and which were four years old.

Customer Insights
Customer Insights was the most-requested feature from the user interviews: real visibility into equipment metrics and service request trends, the exact thing that spreadsheet-keeping customer from the audit had been building by hand. We designed it as the first feature built entirely on ExpressUI, and it doubled as the system's proof. Most of the screens were assembled from the library rather than designed from scratch, and handoff was a conversation about which variants to use instead of hours of redlines.

Making it stick
The drift that built the old portal didn't stop existing because a Figma file said so.
Detaches were signals, not violations. Within the first month I found detached instances showing up in new work, usually a component modified "just this once" for a screen it almost fit. Each one was a fork waiting to drift. Instead of policing them, I treated each as the component telling me it was missing a variant. We started a short weekly review where designers and developers brought the places the system fell short, and those gaps became the library backlog. Detaches mostly dried up over the next couple of months, once people saw that reporting a gap actually got it filled.
The usage guidelines earned their keep. Documenting when to use a table versus a card list settled arguments that component specs alone never touched.
What shipped
ExpressUI shipped with dozens of documented components, each with variants, tokens, and usage guidelines, and every ExpressConnect feature since has been built on it.
Features that used to need custom UI from scratch were assembled from the library in days instead of weeks. The portal redesign brought visual consistency to a product that hadn't had it in years, and Customer Insights closed the loudest gap from the interviews: the reports at least one customer had been rebuilding by hand in a spreadsheet.
What I learned
The components were the easy part. The real work of ExpressUI was getting designers and developers to agree on names, token structures, and usage patterns. The token argument taught me that the hard part of a design system is getting two disciplines to mean the same thing by the same name, and if I did it again I'd involve engineering from the very first token definition instead of after the Figma library was built. The alias layer we landed on was a good compromise. Starting together would have made it unnecessary.
The old system was documentation. I went in assuming the audit was cleanup and the interviews would surface the real requirements. It was the other way around. The workarounds people had built (the bookmarks, the spreadsheet) told me more about what mattered than any interview answer. I've audited legacy products differently ever since.
Kill your own plan faster. The 1:1 port was my pitch, which is exactly why I sat on the evidence against it for longer than I should have. Two weeks wasn't expensive. The lesson was noticing how much harder it is to call a dead end when your name is on the plan.