I recently had two conversations that I can’t stop thinking about. The first was with a prospect. They operate in a very traditional structure of “designers design a thing, and then engineers build that thing.” The emphasis was clearly on the responsibility of design to create intent, and then engineering to interpret that intent into an application.
What do we expect from design tools?
This is a fairly common pattern, and it represents what I like to call the “river” of how we build our digital products. If you can imagine a river coming out of the mountains and flowing downstream toward an ocean somewhere. At the start of the river, there are purely theoretical things (concepts, intuition, research, etc.), and at the end of the river, there is an app that a user actually touches (maybe it’s flowing into an “ocean” of users). Folks often get caught up in exactly where different disciplines sit along the “river”, but generally speaking, design is upstream of development. Traditionally, this makes a lot of sense because of issues with cycle time. The pace of experimentation/ideation in design is typically much faster than that in engineering and it could be said that the river is more narrow and flows faster at the start. Largely, this is because you can create and collaborate around highly detailed compositions that showcase the intended behavior of an application far faster than you can build the application itself. The scope of engineering is significantly wider and not bound by the limitations of a design abstraction — simply put, the river is a lot wider, flows much slower, and causes engineers to have to account for many more things.
The “river” also speaks to the way that most organizations have implemented product production processes — individual teams that are predominantly single-discipline work in agile cycles, but the overall production process largely remains waterfall as an app concept moves through the different disciplines. Further, working with code has traditionally been highly differentiated from design, as illustrated by: alibati.com/horse, “I’m a Mac and I’m a PC”, and a million other memes.
A product is built through a series of transitions and handoffs, most often characterized as “design-to-code”. At the risk of pushing this metaphor too far, the majority of improvement cycles for products are people “waiting for rain clouds”. They’re variable in the time it takes for them to arrive, and we expect them to flow through generally the same process.
So what’s wrong with that?
Design intent into implementation reality
Unfortunately, not every design decision is easily represented by a design tool, and almost no composition contains enough fidelity to bridge the gap between intent and implementation. Every engineer knows that they will need to change or deviate in many small ways and likely some significant ones to actually implement it for a user (and they’re often highly criticized for it!). As a designer, you may be thinking “Sure, maybe there are some small things”, but I assure you that at least several major choices about design implementation are being made in a developer scrum or improvised by an individual implementing a design. Engineers make dozens of important design decisions that designers almost never see or have the ability to review. This is the choice we live with using our current process of standing along the riverbank pushing a Figma file out to float downstream until it reaches the land of the VS Code people.
Even that isn’t altogether wrong. After all, we’ve probably spent some time in virtual hangouts with the other disciplines along the riverbank. We’ve got people in boats (usually called Product Owners) that are frantically shuttling things up and down the river as design reviews, feature changes, and testing feedback finally arrives. The real problem arises when we try to take major changes that occur downstream and bring them back upstream. This can work at a small scale — you can load a few things into a boat and drag them back upstream, but it breaks at any significant scale. The moment you deploy your code it becomes nearly impossible to synchronize what exists in production with what exists in design tools.
This isn’t anyone’s fault. It is a failing of a process that restricts the way we build. The people who are most victimized by this are the product owners who are constantly being asked to move ever larger boats upstream filled with feedback, changes, and new ideas that they have little ownership of.
So, what’s a better way?
The source of truth
This brings me to the second conversation I recently had with Sriram Ramasubramanian, a Senior Engineering Manager at Meta. The crux of the conversation was how they view the relationship between design, code, and any other disciplines that want to leverage the design system. Instead of thinking about the creative process around a product as one that flows downstream, they anchor it in a single mostly-immutable source of truth: the spec. This evokes chilling visions of hundred-page documents and rules lawyers criticizing minor decisions in a seemingly endless threaded discussion. However, what we’re talking about here is much simpler — akin to an API data contract.
This spec is usually a file that contains the agreed-upon values that can change for any given component pattern. It encompasses everything that you’d need to build a component in any destination medium. It codifies decisions about design in a way that isn’t constrained by the capabilities of a design tool. In the case of a button you’d have things like the following:
Notice the stuff that wouldn’t come from Figma.
In this method, there isn’t a transition from design holding the proverbial source of truth to engineering. Instead, any team is free to implement that specification however they see fit. Engineers are used to this, and it is largely an acceptable way of working, but for designers, this is a bit more foreign, and it drives at the fundamental purpose and value of the craft (and a lot of designer trauma around pixel perfection). If you can design any component in Figma that simply adheres to the button specification, does it look like the end result in code? Probably not exactly, but the follow-up question is more direct: Does it matter?
Users don’t look at Figma files. They don’t care if your button in Figma looks like your button on your app. Developers, equally traumatized by the days of pixel perfection, would gladly work from a spec rather than attempting to interpret some new bespoke variation that is “just two pixels to the left on mobile”. Designers go through a fraught process of trying to make their building blocks look like the building blocks that users see. They are salmon swimming upstream against the current. This is often excruciating and incurs a huge overhead; harmonization of code and design is time spent not designing great experiences. It leads many design leaders (who often funded the creation of the design system) to throw up their hands and declare design and development collaboration to be too much hassle.
Why do we actually care if the stuff in Figma looks exactly like the stuff in production? Haven’t we relegated pixel perfection to the same dustbin as the “make it pretty” and “make it pop” tasks for designers? Why go through all of that effort to fight against a concept of central management of systems just to preserve this river we’ve all stood on the banks of for decades? Is it tradition (e.g. does it come from print?) Is it masochism? “But I can’t see what is going to be built!” folks will exclaim. My point is, you already don’t. Rarely do designs make it to users without significant variation. Even more rarely do we review user experiences on the vast plethora of devices, assistive technologies, and screen sizes that our users do. Trying to design what shows up in production is becoming more and more of a fool's errand, and we should abandon it.
Instead, we should embrace design as a representation of intent, and we should base that representation on agreed-upon rules and variations that are shared with our developer counterparts. That is the spec. It will often be more than we need, but it will at least allow us to speak the same language and guarantee that fundamental decisions that impact our users are intentional and understood from concept to implementation.
This changes a lot. It calls into question the fundamental use of design tools for many tasks today. Just as a river's course shapes the landscape, the evolution of design/dev tools should shape our approach to crafting digital experiences. If design is just another implementation of a spec, what role does production design take? This isn’t a post advocating for the wholesale discarding of Figma or whatever your tool of choice is. Is it more about the recognition that these tools are only so valuable as their ability to represent production applications in a way that provides a speed or iteration advantage? That’s a fundamental question that design needs to ask itself at each turn in the process. On the engineering side, we also need to consider how we can democratize access to code for designers who want to embrace working in the medium their idea is destined for.