Sometimes a Great DX Is Just a Horrible Pop Up

Great developer experience isn’t always about polished UIs sometimes it’s as simple as surfacing the right problem at the right time. One small feature I added to our tech estate that always makes me smile when I use it is a horrible global pop up. Here’s what lead me to build it.


The Problem

I work on a mobile app team that owns parts of the backend estate. We often need spin up multiple web services locally and point our simulator at them. We’ve built a GUI that reduces all the complexity of configuring these services down to a few play buttons.

This worked well for years until we started needing to talk to various services using OAuth. To boot these services we now need to obtain a JWT and inject it into the container.

Obtaining the JWTs is easy as our delivery platform team provide helpful tooling. Where we hit pain is that developers are used to starting these services and forgetting about them, potentially having them run for days. This doesn’t work so well now with the JWTs having short expiry times meaning that services start to fail in interesting ways that may not be super obvious to debug.


The Solution

I solved this by adding a global pop up that shows which service’s token has expired and provides a restart button. I could have automatically restarted services but it feels more user friendly to let developers decide when this is going to happen. It looks like this:

An example of the pop up discussed in the post

* The image capture software I used makes this pop up look novelty sized, it’s not this big in reality but it made me chuckle so I’ve left it in.

Design notes on the behaviour of the pop up

How does it work technically?

I’m glad you asked… as the services are all running in docker we can run docker inspect <container-id>, which returns a load of helpful information about the running container. Nestled away under Config > Env is all the environment variables that were provided to run the docker container. We can grab the environment variable that contains the JWT and then decode the payload to get access to the expiry information.

Our tooling is built using Kotlin Compose Desktop so these code snippets are for Kotlin. We start by declaring a @Serializable type that represents the payload and use a handy custom serializer to get the expiresAt value in the right format.

@Serializable
private data class OAuthPayload(
    @Serializable(with = DateSerializer::class) val expiresAt: LocalDateTime,
)

With this type declared we need to unpack the JWT, decode the base64 value and then parse the JSON body.

val (_, payload, _) = it.split(".")
json.decodeFromString<OAuthPayload>(payload.decodeBase64String()).expiresAt

At this point we know when the token expires and we can just schedule for the UI to appear at the right time.


The Result

As a developer I always get a sense of satisfaction when I tap the button and it automagically gets me a new token and restarts my service. I knew the pain of manually getting a token and then trying to remember the right docker commands to stop the running service, export my fresh new JWT then restart the service so I enjoy seeing the friction removed.

As someone supporting other developers, I love that I can’t remember the last time someone came to me that had been tripped up by expired tokens.


Conclusion

Not everything has to be an engineering master piece it just has to solve a problem. These OAuth tokens were a real usability issue for developers who are mainly focussed on the front end, where running backend services locally is more of a secondary concern. The best developer tools don’t just automate they anticipate where developers might trip up and quietly save the day.