To begin, I don’t want to appropriate DesOps in any way and perhaps what I’m about to talk about is not exactly about that. But what I am going to talk about are some first steps we are taking with a client that demonstrate how modern tooling can take them a few steps closer to a Design System.
Let’s start with a bit of history. In the beginning, there was Sketch (bear with me in this first section). Actually, probably Photoshop. Or some other tool like that. You probably know the story: a designer (and I will use the term loosely here, can be UX, can be UI, can be visual designer, service designer or even a dev who paid the $99 to get Sketch) spends quite a bit of time in Sketch creating some super cool assets, then finally hits the export button. A PDF is generated, GreatDesign.pdf, it is promptly emailed to the development team and everyone is happy. Eventually, some changes are done in the next sprint or ten by said designer (or maybe another one), another PDF is generated, GreatDesign_v2.pdf, repeat the emailing, and so on. Then some more changes are done, because some things were forgotten, and, finally, we have the final version of the design. So now we have GreatDesign_final.pdf. And that’s it. Or is it? Wait, we forgot a few things so, finally, finally, we have GreatDesign_final_final.pdf. Or do we? Because there is also a GreatDesign_final_final(1).pdf. Oh dear. Oh dear. Oh dear indeed.
Ok, enough with the third-rate sarcasm! Things have moved on a bit from the above – there’s stuff like Axure, Zeplin, InDesign and a few more that sprang up while you are reading this. At least your designs are now organised, developers have a link to go get the latest, and we can all agree on what the right version is. You can even get some code samples or even fully working prototypes (the value of which, when it comes to how usable the code is, we can debate another time). Let’s have a brief look at what the workflow may look like using these tools to create a couple of apps:
Figure 1: From Sketch to Apps
I’ll assume some basic knowledge of what Sketch does so I can concentrate on the rest. You could argue that the PDF is now obsolete and there are tools like Zeplin. However, with Zeplin, while we may get some measurements on how things should be laid out and also get some autogenerated CSS, we still need to manually copy and paste all that into our code. Additionally, Zeplin will not tell us how the responsive layout should work, what happens in the in-between states and other things like that. It is just a nicer way of handing over from design to dev. As such, there are a whole raft of things that are left open to interpretation, plus a lot more that will just fall through the cracks and not surface till QA has a go at our app. Still, it is an improvement, as we now have an easier way to get to the design vs. trawling emails and PDFs.
Figure 2: A solid line denotes “automation” while the dotted line is manual work
Let’s see where we are now. It is easy to find the designs, but what about the code? Right now, the only way to see what assets are there is to look at the code, the actual apps, and then take screenshots to catalogue them. Not that easy. Now, in our particular case these happen to be React apps. As such, we can do something very easy: use Storybook. I’ve written a bit about the React toolchain here, but, in a nutshell, Storybook will visualise our components, our actual React components, without having to run the app. As such we can now catalogue our components.
Let’s see those apps then. We’ve taken the example of a bank on this occasion and we made a couple of simple apps: one to see your account statements and another to pay someone.
Looking at them (please ignore the garish design, this was a POC made to look a bit off on purpose), we quickly see that we have a couple of common things: a header and a footer. In fact, we probably have three: a header, a footer and the buttons. Or maybe we have a few more, like section titles and so on, depending how we break them down (atomic design, anyone?). We may also note that the buttons are different: one app has square buttons, the other rounded ones. This is a reality (not for a button specifically but for consistency overall) for many organisations where designs have to be translated to code again and again. The same design ends up slightly different in various parts of the system and, sometimes, even the design files end up diverging.
As such, the next step is obvious: create a component library! I say obvious, but it is surprising how many organisations actually do not have one. So let’s see how things will look with a component library:
Figure 3: Introducing the UI component library
As such, we now have a library of common components. We can update them in one place instead of two (or three, or ten, or fifty). Not only that, but notice how we have gone from two manual updates (copy/paste) in the first diagram, to one automated export plus two manual updates in the second diagram, to three automated updates and one manual action in this. We are now automating more updates than we do manually. As such, we are now close to using the automation capabilities of our CI environment as part of the design process. For now, our library is packaged and distributed and any updates end up in the apps automatically.
Additionally, we can use Storybook in our library to see the components, plus use the rest of the capabilities that come with it: interacting, testing, commenting (again, see this on how Storybook helps with all that).
What we now have is a sort of living style guide within the development domain. However, that still leaves the rest of the process outside. In the video above, the last thing we see is someone commenting that the colours are all wrong. What next?
As it is now, a designer would have to make a change in Sketch/Zeplin. The developers would then have to deconstruct what they see, interpret it and write the code for it. That bit in the middle – the “interpret” – is where mistakes happen. Let’s see how we can improve on that.
Enter Brand.ai. The first thing Brand.ai does is to give us a Sketch plugin. As such we can now export from Sketch to brand.ai components, styles, images, etc. We can also upload assets direct to Brand.ai. For example, we can have all our logos and colours for the brand identity. We also get bidirectional updates: update something in Brand.ai and the Sketch file gets updated too.
The next important thing it has is an API to extract that info. Therefore, within the build process of our app, we can hit that URL, download the latest assets and use them. Here’s what our system now looks like:
Figure 4: Introducing Brand.ai
Notice how we no longer have any manual steps (by which I mean copy and paste type stuff). We have linked design into our CI environment. Finally, to enhance collaboration and distribution of information, we can hook into Slack and get notifications. When updates occur, we get notified that a new version exists. When we comment on blabbr, we get notifications on Slack. Here’s what it actually looks like when working with it:
All the above shows us is how we now can update our UI library, automatically, by initiating a change in Sketch. Once we can do that, we are ready to update the actual apps as well. As such, we now have end-to-end flow, from design to production. That last word “production” is the most significant one, as that is what our customers get to see. It is important to realise that in our diagram above, once we hit the app box (App 1, App 2, etc) what I mean is that we are hitting the point where the app is ready to be deployed to a live environment.
Hold on. You may ask if that all this is probably a bit too much trouble. We’ve added yet more tools, changed a lot in our environments, our processes, how people work and all that to get rid of that manual step in Figure 2. Yes, we have. Let’s have a look at that diagram again:
That is a nice little example of a very simple system. The reality is that for starters, there is another line from Zeplin to each of the apps. The reason? Our UI library may have a lot of components, but it will not have all of them. There are always app-specific things and, in any case, the views are owned by the app. These need to exist as code too. So our diagram is now this:
This also covers just one platform. Most places will have a mobile platform, web and web apps too. You may have a few dozen apps per platform too. As such we would be looking at something like this:
A lot of manual work here
That is a lot of manual work, work that will inevitably go wrong: things will get misinterpreted, and as such quality and consistency will rapidly decline. It is also interesting to see that, since the jump from Zeplin to the library is manual, the automation to the right of each library will simply amplify any errors. Here is the alternative:
Still complicated but at least everything is automated
Still a lot of lines, but at least they’re all linked. So any mistakes can be rectified very quickly – any updates too – and we are always taking advantage of all the CI tooling. If we collapse this back to the lines via the libraries, we have only this:
You’ll notice I rearranged the library boxes a bit. We now have a web (ie. HTML/CSS) library, a web app (ie. some JS framework like React) and mobile. Imagine then how we can start sharing some styles between the different components. In the end, the top two are both running in a browser, as such with a bit of clever thinking we can start sharing CSS between them. In fact, we could share CSS with our mobile components too, depending on our technology choices.
That may start looking complicated quickly. However, the importance of it is that we have now automated changes. We have also reduced the number of sources. Instead of having a plethora of style guides, PDFs, Zeplin pages and the rest, we have a living style guide. This gives us access to the actual components that are going to be deployed to production, as such we no longer have to make assumptions about what will be delivered, we are looking at it.
We can also start prototyping without having to use off colours or fake components. We can do that using actual components and styles. The importance of this cannot be underestimated. How many times have we found designs, styles and code that were supposed to be “just a throwaway POC” in production? I’ve certainly found them myself, I even put them there on occasion. In fact, let’s have a look at how this looks like.
We can see then how a working prototype can now be created using our existing components. We can also see what components are available and thus make some more informed decisions: as opposed to a prototype coming up with more and more components that are just ever so slightly different to what is in the library, this either increasing the number of components or ending up using components that do not do exactly what is needed.
We can keep going and start adding more concepts, showing how testing fits in, e.g. kicking off accessibility testing well before the app is created, how copywriters can try new copy using the living style guides, etc.
People do not make mistakes on purpose. They do not set off to write bad code. They do not start a new UI kit just because they want to play or introduce inconsistencies. In the vast majority of cases, these things happen simply because they just want to get on with the job of building something vs. trying to find what tool to use to build it. In some cases it even just comes down to internal barriers, perhaps a department not sharing their designs and code, or just IT security making it impossible to share a PDF or use a hosted service. So people find workarounds hoping they will do something good.
What we are trying in this particular instance is to:
- make collaboration as easy and smooth as possible
- automate as many steps as possible to reduce mistakes and inconsistencies
- make as much as possible visible for others to find, thus encouraging reuse and eliminating waste
I have probably over-simplified a few things. I’ve also used certain technologies and tools in the above example, but that is purely because these are the things we are currently using. That doesn’t mean that what we are doing is limited to just those. In any case, whatever we choose today will probably be gone in 3 years and there is something new starting as I type this. What matters are the principles that drive a design system, as these are what DesOps need to apply and support. Hopefully, our little example here can help demonstrate some of the things we can do, in order to get everyone working closer and better together.