Get past the high fan-in dependency mess
A design system team is in the organization to serve the entire organization. With this mindset, I started running a design system team and very soon found myself debugging the organization, where that team was being declared as a “dependency” or, occasionally, a “blocker” to most other teams. What happened?
I don’t think that people were trying to be mean or they were trying to hedge their chances. They were trying to be honest and transparent, and I appreciate that. But at the same time, it honestly hurts to be in a place where, if any single project in any of the teams goes wrong, it’s gonna be held against your team where people are genuinely trying to do the right thing. We can talk about stakeholder management here, but let’s keep if until next time.
This is how it went:
we started with a mission to improve the organizational productivity and make the look and feel of the product more cohesive
then we bumped into the high fan-in of dependencies
and then we figured we need to flip the script!
Don’t trade futures
The main drama of design systems work and organizational dependencies is a prioritization exercise. It’s when the design system team’s product manager runs some numbers, gets some “asks” from the teams, and comes back with a list of all possible improvements. They weight in other things, such as the distance to completion or potential impact. Team members include data on design and tech debt, debate optimal sequence of projects, and add some parameters to the decision-making model. Everyone checks when they’re going on vacation in the next 3 months. In the end, there’s a list of projects, carefully prioritized. Top of list is usually some sort of a date picker. Something high-impact. The team is pumped up about that: yeah, let’s create that date picker! make 7 out of 30 teams happy! unlock some serious product success!
Took me personally a few times like that to understand that, whatever the project is, the result is projected to realize in future. We don’t have a date picker right now. We have to work on it, as well as on many other things. And hey, it’s actually very hard to make a date picker that doesn’t suck.
Lesson learned: don’t make promises. A design system team’s shortest path to frustration is promising to deliver something in future.
What to do instead:
- rely on what the design system contains right now, this very moment
- be realistic about the amount of time your team has that can be spent building to other team’s needs: this approach is very hard to scale
- suggest local implementation first
Rely on what’s available right now
This might sound like advice for established design system teams, with a long list of tools and building blocks ready to be used. But stick with me — this can actually work for early-stage teams, too.
How do you avoid promising anything when you have nothing to show? Two things that I found helpful: lag purposefully and embed into product teams.
By lagging purposefully I mean committing to catch up with what a product team needs eventually. For example, if most teams need a way in the UI to get some rich text input from the user, it would be a better idea to declare that there’s no rich text input component in the library right now, period. No “and it would be awesome to have it” and of course no “so we’ll build it”. You stop talking right after declaring the fact that a rich text input component or pattern does not exist in the design system. They you start working on it. If the problem is widespread enough, you should have heard people wishing for a solution multiple times already, so eventually, when the design system team delivers it, teams will be happy. It’s so much easier on the team when there are no expectations to manage.
By embedding into product teams I mean for the design system folks to build spot teams with folks from the product teams to implement a first iteration of, say, a rich text editor. Co-create. This way you split the effort and extend the capacity of the design system team by people from product teams who are going to be supporting. Coordination becomes a problem, but hey, that’s a job you should staff for.
Be realistic about effort and complexity
If I’m on a product team and I need to ship a feature where one of the inputs is a date, I’m going to look up something on npm and install a package with a date picker that gets the job done — for now. If I’m experienced enough, I know that I’m subscribing the team for months and years of added maintenance work, hunting peculiar bugs, fighting against rigidity and lack of customization options in that package, and the ever-decreasing sense of ownership because “we didn’t create it, someone else did”.
If I’m on a design system team, sheesh, that sounds like a lot of work! I mean, dates are weird. Making it accessible isn’t trivial. And there are so many teams, each having so many needs. What if we need to get a date interval instead of just a date? Time included or not? Localization?
My only bit of advice here — for you and for future me who is probably being very optimistic right now — to, knowing the amount of effort already, just be very thoughtful about the amount of wall clock time it’s going to take to get that done.
See, a design system team presents many jobs that need to be done and require time to do so. If it’s realistic to expect the makers on product teams, on average, to spend 60–70% of their time towards the product goal, that number is about 10–20% on a design system team? If you zoom into a random day, this percentage might be even lower.
A good way to make it work is to first let a product team go past the “ask” and actually implement a solution they wish existed as part of the design system. It’s almost guaranteed that tier first implementation is going to fit maybe 50% of their needs; second, perhaps 80%. The numbers are arbitrary, but you get the point: there’s never a perfect solution; one can only asymptotically approach it over time. Let’s talk about that.
Local implementation first
“Local” here means “right there, in the product”. So, not in the design system.
If you run a design system team in the org as more of a coordinator and less of a builder, you probably employ the approach where the design system grows by external contribution. The team gets some inbound requests, but never implements them directly, rather choosing to support the author of the request who is actually implementing the change. The “local implementation first” is a variation of that.
So if a product team is asking for a date picker, tell them they can solve the problem in any way they want, and only after that this solution is going to become part of the design system, — eventually. In the end, a design system should represent reality, not ideal state, and nothing supports this stance more than making what already works in the product generic and reusable, yet still concrete and grounded in reality.
Once the local implementation is rolled out to the end users, observe it. Watch the bugs. If you have enough capacity on the design system team, get one or two team members support with fixing those bugs.
Once the local implementation is successful — as in, the product team who implemented it has been running for a while without having to stop and fix bugs there, it’s time to migrate the implementation into the design system. This is actually not trivial: you need to retrofit it into the system, rebuilding it from the level of tokens, writing design and technical docs, and communicate the progress a lot. Then you need to get the product team who authored the date picker to refactor the code, so that the one from the design system is being used. It’s pretty hard, but it’s still easier on people than being in the epicenter of implementation while getting indirect feedback (via product teams).
One mistake I’ve seen is saying “we’ll add it to the design system after it’s battle-tested” and never doing it. Happens so, so many times. Work with your PM to make sure they, and therefore the team, are aware that this work is not forgotten or deprioritized in favor of a more recent “urgent ask”. Be strict about following the definition of done.
With dedication and a little bit of luck you’ll populate the design system with components, patterns, and other building blocks over time without making teams feel like (or explicitly declare that) they depend on your future delivery.
This post turned out to be more practical, less abstract, and so should fit a narrower set of readers but for them be a more actionable and useful manual than any high-level overview of a process. Hope you find it useful and/or relatable. Ping me on Twitter and let me know what you think!