Using GraphQL & Backend-Driven UI, to build faster with less code
Backend-Driven UI is an exciting pattern recently recognized by Airbnb (more on this at the end). In this article, I will outline how we utilized the same Backend-Driven UI principles to improve the way we handled some complexity in one of our projects. This is simpler use-case that anyone could implement right now!
The problem: Statuses get complex
The project we were working on had a “status” problem. A problem that I have found is fairly common across development teams and projects.
The GraphQL schema defined a status type that managed the state for each node of data in that type. These statuses were stored as a constant, or what I call an “ugly” database value. Definitely not something that would be okay to display to a user. Often these statuses are not only computed based on the user requesting them or “viewer” but on related types as well. This meant every client had to translate or write additional logic when presenting these statuses in a meaningful way to the user. Fortunately, GraphQL is great for combining pieces of data and calculating values! Here’s an overview of what we did in the context of a pet adoption website. Just Because who doesn’t love puppies!
Imagine we have a GraphQL schema that looks something like this, with a few types that require some sort of status or state management:
First, you will notice the adopter and the adoption types. Each includes a field that stores the current status for that node. When an Adopter applies to adopt a Pet they enter into an Adoption contract. That contract information is stored in the database and defined by the adoption type, which has a state. Not only does our database need to keep track of the state of each adoption but the verification state of each adopter as well.
Each adopter needs to pass a verification process to make sure they are qualified to care for their new puppy! That information is stored on the adopter type rather than the adoption, however, it is still an important part of the user journey and needs to be clearly articulated on the client.
Imagine a UI that looks like this:
Pretty simple and straightforward. We display the adoption details in a layout that stays consistent. The presentational components accept the data from the API and display that information accordingly. It’s not overly complex to just handle the status logic on the frontend. Maybe a switch or if statement to quickly display the correct info and pretty up the server response. For instance, instead of reading PENDING_VERIFICATION it reads “Reviewing your account”. Sure, that’s quick and simple!
However, What happens if there are even more statuses and complex flows. What if you have different use cases across different frontend applications? Web? Native? Email templates? SMS? Does that mean this logic needs to be rewritten in every case? Quite often, yes. So, what if instead, we let the GraphQL API do the “talking”.
A Backend Driven UI Approach
This is an overview of how you could use Backend-Driven UI to simplify the developer experience and solve the status problem.
How to set it up
You start by extending the adopter and the adoption types with a new field defined by the StatusIndicator type. The StatusIndicator type includes a status title, description and any color necessary for emphasis. When you create this new type definition, focus on how it will be used on the frontend. You may find other styling or copy information may prove useful, like buttonText. Here’s and example of the new type definition:
Then we set up the resolver:
I removed some of the additional status checks to speed this up, but the idea is that within the resolver you can now combine statuses from separate types and even disparate services to resolve the statusIndicator field. In this case, we query an external service to access the adopter’s verification status and return the relevant frontend copy and styling accordingly.
Here is the before and after frontend code resulting:
The frontend code looks more like this (Assume props are direct results of our query):
and less like this (Props are direct results of our query):
The new components are succinct and simple. Instead of the worrying about what they should say and in some cases how they should appear, the API consistently delivers that information no matter the device requesting. For example, the success status will always be green and read the exact same way across all frontend clients!
So, what benefits did we receive from this pattern?
- More consistent and enjoyable developer experience across teams.Now, developers don’t have to re-implement the same code across every client. No more worrying about the design and copy requirements individually, the API handles it!
- Reduced frontend code. The project had been worked on by numerous developers and had to handle all of the status logic prior to rendering! There was a ton of unnecessary logic transforming these statuses into the right wording and design patterns. Now, we have removed all of that code equating to hundreds of lines!
- More consistent user experience! Most importantly, is the benefit this has had on user experience. Now, users and admins receive consistent communication across all frontend clients and transactional messaging!
Obviously, there are many ways this can be improved and no single pattern works for every case. That being said, our team believes that this experiment was remarkably successful. It became more evident that GraphQL is so flexible that it allows developers to think creatively while challenging traditional conventions.
Shoutout to Airbnb for the ideas!
A recent article written by Adam Neary at Airbnb does an amazing job painting a picture of what it looks like to apply a Backend-Driven UI approach to build beautiful user experiences 10x faster!
His demo from the GraphQL summit and the article that followed outline how Backend-Driven UI looks when it is used to adjust the entire layout of a page, and determine how a frontend should render content and copy. It is really cool to see entire pages built this way!
Until then, this was our simple interpretation of the pattern and I hope you found value in the article! Thanks for the read!