Gympass front-end architecture redesign
By: Kaic Bastidas
Tags: Front End Development, Nextjs, Kubernetes, React

Other than these 3 main problems, we also have a lot of legacy code that has a lot of code smell and bad practices. We also have a HUGE boilerplate to create anything, be it new page routes or API routes on our integrated BFF. Having the BFF and the SSR engine on the same server also means that we have coupled them and there’s a single deploy pipeline for them both.

Also, having these problems really discourages us as engineers on creating new front-end services and that made our current repositories turn into little monolith applications with multiple contexts inside of it.

And since we did not have the habit of documenting things, we have a pretty bad documentation of the current stack.

The solution

Let’s solve our problems one by one, shall we? The first problem is that it is very difficult to create a new service. To solve that our SRE creates an inside tool that we call Josie.

Josie takes a template as a parameter and generates a new service from scratch, creating production and homologation environments with just a simple command.

That’s it. We now have a simple app running on production with a single command. There are still some config’s that we have to do manually, but this CLI simplified our life a lot.

Now all we had to do was to create the template. We thought about it and reached the conclusion that we can be more productive using an existing framework, with an dedicated team working solely on the SSR engine, then trying to give maintenance to an in-house engine WHILE creating new user experiences (we may change this vision on the future, when our team grows and our platform gets more robust and that’s absolutely normal). That’s why we’ve chosen Next.js.

Gympass + Next.js = ❤

We proceeded to create the template with everything that we thought would be necessary to develop our future features. We then got to the next problem: what if we wanted to change something to all the services that use this template?

To circumvent this problem we created an internal package to be used on the template, with everything that we thought was core for our application. Configurations, helpers, components, you name it, we have it all inside this package.

When we change something, all you need to do is bump the package version on your package.json and get the latest code. We reached this final infrastructure:

Final service structure

We still have the last problem to solve, which is multiple BFF’s with the same API’s. This was probably the biggest change in our developer mindset. To power our current native app (iOS and Android, written in react-native), we developed a GraphQL BFF which was being used only for the app. We were not using it on the web because as explained before, changing the core on our legacy code base was pretty hard.

We took the opportunity to create this interface with it for the front-end applications too, allowing us to keep the same logic in a single, concise, place. Now features that exist both on the app and the web can use the same queries to build the interfaces. This is a dream come true.

Our example, following this new structure would look like this:

Our legacy application uses Redux to manage the state of the application, now we only rely on Apollo to do that (that’s why this was a big mindset change).

Although this change is pretty nice, we didn’t want to force it, that’s why we made the Apollo provider optional through a higher order component, which also comes from our core package. This is an example of the final result:

With this current stack we also solved the other problems that we had, with a new and better code and less to none boilerplates.