Balogun OluwasogoWriting

The Space Between Design and Engineering

Some thoughts on how learning to build software changed the way I think about design.

Introduction

Published
Reading time
6 minutes

I started out in design towards the end of 2021, taking Google’s UX Design Professional Certificate course. I was interested in how digital products were designed, how people interacted with them, and what made some experiences better than others.

After that, I started freelancing on Fiverr and Upwork, mostly working on websites and interfaces for clients. I enjoyed the process, especially seeing something go from an idea to a finished product.

At that point, most of my attention was on the design itself. How things looked, how people moved through a website, whether the layout made sense, and whether the experience felt right.

I understood that someone had to build these things, of course, but I didn’t fully appreciate how much of the experience was shaped during implementation.

That changed when I started writing software professionally.

Getting into engineering

In 2023, I joined AXA Mansard through its Executive Trainee programme. That was the beginning of my software engineering journey.

I started with frontend and mobile development, working on applications that people actually depended on to get things done.

It was quite different from freelancing.

For one, I was working within existing systems and codebases, alongside other engineers and teams. There were business requirements, dependencies, deadlines, and decisions that had been made long before I joined.

I also started seeing how much work goes into making even seemingly simple features behave properly.

Take a form, for example. From a design perspective, you might be thinking about the layout, field grouping, labels, and how easy it is to complete.

When you’re implementing that same form, you also have to think about validation, API responses, loading states, errors, permissions, and what happens when someone does something you didn’t expect.

And those things affect the design too.

An error message needs somewhere to appear. A loading state needs to communicate what’s happening. Validation rules can change how a form should be structured in the first place.

I started paying more attention to these details, even when I was doing design work.

The things you don’t always see in a mockup

One thing I’ve noticed is that it’s relatively easy to design for when everything goes right.

The data loads, the content fits, the user follows the expected flow, and every interaction behaves exactly as intended.

Real applications are rarely that straightforward.

Sometimes a request takes longer than expected. Sometimes the data is incomplete. Sometimes someone clicks something twice, or tries to do something they don’t have permission to do.

These are all things that need to be accounted for, and they can have a pretty big impact on the experience.

Even when everything works, there are smaller details to consider.

Does an interaction respond quickly enough? Is the feedback clear? Does an animation help someone understand what’s happening, or does it just look nice?

I’ve come to see these as design and engineering decisions happening at the same time.

You can design a really nice transition, but how it’s implemented affects how smooth it feels. You can build a technically correct feature, but if the feedback is confusing, people will still struggle with it.

The two constantly affect each other.

Here’s a simple example. Try submitting the form under different conditions and see how the experience changes.

One form, different realities

Network conditions

Join the waitlist

Leave your email and we’ll let you know when it opens.

This demo needs JavaScript. Nothing you type is sent or stored.

A gradual shift in perspective

Around 2025, I started taking on more backend and full-stack work, and this became even more apparent.

There wasn’t one particular project that changed how I thought about things. It was more of a gradual realization from working on different projects and running into different kinds of problems.

I’d be implementing something and notice that a small technical decision had implications for the user experience. Other times, I’d be designing something and realize that understanding the underlying system would help me make a better decision.

I’ve seen this play out in some of my personal projects too.

With the Ace Trail Tutors website, for example, I spent time working on the motion and interactions. Getting the animations to look right was one part of it. Making sure they performed well, using transforms where appropriate, and accounting for people who prefer reduced motion were just as important.

Here’s what the hero looks like with and without the full animation.

With full motion, the hero rises into place as the page loads, and the photo grows to fill the window as you scroll. Both recordings use the same 1440 × 900 window and the same scroll.

With reduced motion, the hero appears in place, and the photo jumps to full size halfway through the scroll instead of growing. Both recordings use the same 1440 × 900 window and the same scroll.

JobTrackr was a different experience.

I designed and built it to help people manage their job applications, interviews, documents, and other parts of their job search.

There’s the visible side of the product: the interface, the flows, the interactions, and how everything is organized.

Then there’s everything supporting it. The database, authentication, permissions, API requests, error handling, and all the other things that need to work for someone to use the product reliably.

For instance, making sure one user can’t access another user’s applications isn’t something you’d notice from looking at the interface. But it’s a pretty important part of building a product people can trust.

Here’s a quick look at JobTrackr. The interface is only part of what’s happening, so I’ve included a few notes on the engineering behind it.

Recorded from JobTrackr running locally, with a sample account and sample data. The video shows the interface. The notes describe the code behind it.

Interface

Adding an application opens a drawer. The form checks what you’ve entered when you save, and the server checks it again. A new record gets a confirmation with a link to open it, and moving it from Saved to Applied adds the submission to its activity.

If the server doesn’t answer, the form says the save couldn’t be confirmed and keeps what you typed, so you can check before adding it a second time.

API & authentication

Saving runs a server action in the Next.js app. It reads the signed-in session on the server and calls the NestJS API with the access token in an Authorization header.

Every API route that isn’t marked public sits behind a guard. It checks the token’s signature against Supabase’s published keys, along with its issuer and audience, before any handler runs. Without a valid token, the API answers 401 and the app asks you to sign in again.

Data permissions

The API takes your user ID from the verified token, never from the request body. Every application query is filtered by it, so asking for someone else’s record finds nothing and returns a 404.

In the database, row-level security policies tie each table to its owner. They’re a second layer for anything that reaches the database with a user’s token, and client roles can’t write the fields that record where an application came from.

Working on projects like these has changed how I approach both design and engineering.

I think more about how the whole thing works, rather than just the part I’m currently working on.

Somewhere between the two

I don’t think every designer needs to become an engineer, or that every engineer needs to learn how to design.

There’s a lot of value in specialization, and I’ve worked with people who are exceptionally good at what they do because they’ve spent years focusing on it.

But I do think understanding a bit more of what happens on the other side makes a difference.

As a designer, knowing how things are built helps you make more informed decisions. You start thinking about performance, accessibility, and technical constraints earlier.

As an engineer, understanding design helps you look beyond whether a feature works. You pay more attention to how people experience it, whether the interaction makes sense, and whether there’s a better way to approach the problem.

Sometimes that means simplifying a design. Sometimes it means putting in extra engineering effort because a particular interaction is worth getting right.

And sometimes it means questioning the original approach entirely.

I think there’s a real craft in being able to move between those perspectives, understand the trade-offs, and make decisions that account for both.

Still learning

These days, I work across product design, frontend development, backend systems, and whatever interesting thing I decide to experiment with next.

I still enjoy design for many of the same reasons I did when I started. I like good typography, thoughtful layouts, interesting interactions, and the little details that make a product enjoyable to use.

I also enjoy figuring out how things work, solving engineering problems, and building the systems behind those experiences.

There’s still a lot I don’t know, and that’s part of what keeps it interesting.

I don’t really see design and engineering as separate interests anymore. They’re both part of how I approach building things.

And I want to keep getting better at both.