Streamlining Frontend-as-a-Service for Backend Teams

How We Built a Working Process to Accelerate Product Delivery

Experienced application developers know the challenges of building a simple and intuitive frontend for an app. Frontend activities such as User Experience (UX) Design, mockups, prototyping, and User Interface (UI) Development take a tremendous amount of time and effort, especially for those who focus on the backend. What happens when a typical backend developer tries to build the frontend? Well, you tend to get apps with difficult usability, inconsistent styling (e.g. iconography, colors, layout, etc.) and poor user satisfaction.

Photo by Helloquence on Unsplash

Before I joined the UI/UX team at Walmart Labs, most teams in my org consisted of backend engineers who were also responsible for building the frontend. Other teams fortunate enough to have frontend engineers lacked UX Design. Overall, this org structure resulted in an inconsistent and over-complicated user experience across our tools platform, which still exists today.

Check out my first blog about Designing a Loading Screen to Fit Your App.

That’s why the UI/UX (frontend) team was formed; to disaggregate the frontend layer from backend development teams and promote scalability and consistency. We established a Frontend-as-a-Service (FaaS): providing UX Design and UI Development services for more than 5 teams. We ran into many unforeseen challenges in our first few months, but after a few iterations, we were able build a working process to minimize these challenges and uncover the unknowns.

Frontend-as-a-Service Flow with Backend Teams

Uncovering the Unknowns

As with many software development teams, we face unknowns whenever we start a new project. The two types of projects we usually support are: New frontend builds (building from scratch) and frontend revamps (rebuilding for existing app).

Often times when a new project would kick off, we would discuss feature requirements, create mockups, and before our team starts UI Development, I would ask the question:

“Are your APIs ready?”

Most of the time, they would say yes. Most of the time, they were not. These circumstances would block our team’s productivity and delay the project’s timeline. We usually faced challenged that fell into two categories: API design and coupled full-stack code issues.

API Design Issues

An API, which stands for Application Programming Interface, bridges the communication from frontend to backend servers. The purpose of an API is to define the app’s functionality and act as a messenger in delivering client-side requests (frontend) to the server-side provider (backend).

API Communication

Ever play the game Telephone? If you have, then you know what happens when a message is completely botched through communication or interpretation errors. That’s essentially what happens with a poorly designed API — frontend developers will misunderstand how to use them.

Here’s a great blog I found about API Design Guidelines.

Some common issues we faced with API designs are:

  • Missing parameters: Fulfilling certain requests often require parameters in the API. For example, if you want to GET a specific device from a full list of devices, a parameter should be used to query with a specific ID. e.g. /devices/{deviceID} If the APIs were not designed with the necessary query parameters, presenting that data becomes a greater challenge.
  • Non-optimal response structures: The API response structure is important when it comes to the overall app performance. For example, if we wanted to display a list of devices grouped by model in the UI, but the response was written in a single-stringed array (in random order), querying and displaying that data would require frontend processing that would slow down the app. The example below shows an optimal and non-optimal response structure based on grouping of device models.
# Device arrays grouped by model (optimal)
"model1": [{mod1_details1}, {mod1_details2}]
"model2": [{mod2_details1}, {mod2_details2}]
"model3": [{mod3_details1}, {mod3_details2}]
# Device list array (non-optimal)
"devices": [{mod1_details2}, {mod3_details2}, {mod1_details1}, {mod2_details2}, {mod3_details1}, {mod2_details1}]
  • Missing completely: This one is pretty self-explanatory, but you’d be surprised how often we’d start UI development to find the APIs have not even been developed yet.

Coupled Full-stack Code Issues

Coupled full-stack code issues are only related to Revamp projects. Sounds easy on paper; the app is already fully developed and in production. What could go wrong? Well, when frontend code is tightly coupled with the backend, separating the code takes time, especially if the app’s functionality is not well documented. Two common issues we’ve faced are:

  • Coupled coding structure: Full-stack developers have the ability to code app functionality in the backend, then immediately visualize that functionality in the frontend. Since both sides of the code is written in the same file, this often makes it difficult for frontend and backend to coexist independently.
Coupled Full-stack Coding Structure
  • Lack of documentation: Developers building apps with a coupled coding structure tend to skip over documentation since the app already works. Trying to understand the app’s functionality without well-written documentation is like trying to learn another language with no translation. You might be able to understand it, but you’re most likely interpreting it wrong.

Now you may be wondering, why don’t we just hire all full-stack engineers and avoid the frontend-backend complications? The answer is simple — it’s extremely difficult to find full-stack engineers who are equally skilled at both frontend and backend development. And when you do find those purple unicorns, their scarce population makes it extremely difficult to scale. (Perhaps I’ll elaborate on the pros and cons in a future post.)

Building a Streamlined Process

Our FaaS lacked a smooth working process with backend teams; we were constantly getting blocked, going back and forth trying to figure out what we needed. To prevent unknown issues, we built a streamlined process that provides our frontend team with clearer requirements, well-documented APIs, and validated mockups in a streamlined process.

Although this process was developed to support frontend-backend team relationships, full-stack developers should also consider following these steps to accelerate product delivery at scale.

Develop User Stories

The first step, which is the basis of Product Management, is identifying the user base and building user stories. For every project, including revamps, we start with this step to validate feature requirements. We found that even existing apps had functionality built without the user base in mind, such as including admin-based features in the main UI. By developing user stories, we are able influence change, prioritize requirements, and ensure the UI aligns with our targeted users. We often develop user stories throughout the entire development lifecycle, as we continously refine and discover user needs.

Establish a Data Contract

One of the biggest gaps in our process was the lack of clarity and visibility into the backend code. We established a data contract to capture pertinent information such as the URL, request type, and JSON response for the API endpoints. This contract enforces documentation and creation of APIs that separate the backend from full-stack code. By building a data contract upfront, we’re able to align data types to user stories, identify API design issues early in the development lifecycle, and ensure the UX design aligns with the app’s functionality. The data contract has been the primary solution to minimizing unknown issues and decoupling full-stack code.

Exposing APIs by Establishing a Data Contract

UX Design: Mockups

After performing user research, we leverage user stories and data contracts to develop mockups. Mockups bring the app’s requirements to life with design visuals that show what the UI will look like and how the user will use it. There are various stages for mockups: from rough sketches, to wire framing, to static colored pages, and finally to something interactive (e.g. clickable, swipeable, etc.). Mockups provide tangible artifacts that allow us to obtain user feedback easily, provide clarity into what we will build, and enable stakeholder buy in. In addition, mockups validate the data contract and gives visibility into the necessary APIs before building.

Example Wire Framing Mockups

Obtain Stakeholder Validation

Once we have the mockups, we’re able to demo the designs to our stakeholders and obtain validation. The data contract and mockups provide a common language for frontend and backend teams to clearly communicate and agree upon app requirements. This is usually an iterative process where we continuously discuss proposed features, while refining the data contract and mockups as needed.

UI Development: Coding

Last, but not least, we are finally ready for development. By empowering our frontend developers with validated mockups, well-designed APIs, and data contracts, they are able to focus on coding with minimal disruptions.

Data contracts also enable our frontend developers to create mock data for UI development. This means that we are able to create identical API responses to build the UI, even if backend teams are still working on them. We’re currently using local servers to mock the data, but will also explore creating mock server libraries that can be used collaboratively with the team.

Check out this blog about mock server libraries by Himanshu Jain.

Learning Lessons for All

Our new process have not only accelerated the app development lifecycle, but has also driven an overall greater experience for end users. Even though our challenges and solutions are based on our relationship with backend teams, the lessons learned and overall journey is applicable to any multi-team working environment.

Photo by rawpixel on Unsplash

The key to any successful working relationship is communication, but clear communication only works if you’re speaking the same language. And no, I don’t mean English; I’m referring to a common language that must be created between the teams to drive successful communication. In this case, our common language are the data contracts and mockups, which resolved majority of our issues with backend teams. You should find a common language that mutually works for you and the teams you work with.

I’m always looking for new ways to improve our process. If you have any suggestions or have had a similar experience, please share in the comment section below.

Did you find this useful? Please recommend or share, and feel free to hit the clap button. 👏🏻 Follow me for future posts.

Walmart Labs is continuously solving problems to enhance the software delivery process and user experience. If you are interested in joining our mission, check out our careers page.