Building a disruptive frontend for commercial insurance
By: David Makuni
Tags: React, JavaScript, Front End Development, Insurance, AI

Our library of choice at Cytora is React and the Underwriting Productivity Suite (UWP) is the primary frontend application we are currently working on. React.JS is a fantastic library that is used in modern single-page applications in particular — which means they don’t refresh as you click around. Strong industry backing from the likes of Facebook, who are also the creators, makes it a very safe choice.

The product itself is designed to help insurers reduce expense ratios and deliver profitable growth. The suite uses our proprietary APIs to augment submissions as they come in, filter out risks that are out of appetite for the insurer, and prioritise these submissions according to their value.

Along with this application, we also have a collection of micro-frontends focused on a single responsibility, all using React and react hooks for state management, styling, side effects, etc.

The move to monorepo

Naturally, this presented my first challenge at Cytora. Having many frontends in separate repositories has the tendency of encouraging code duplication i.e., having almost identical pieces of code doing the same thing.

This can grow into a maintainability nightmare because if you need to make an important change, for example how you login, you have to make it in all the frontends. Making changes like these across many repositories is messy and difficult to track, and testing across repositories becomes complicated very quickly.

Typically, some companies would approach this problem by supporting both ways of doing the same thing, only upgrading the frontends which need this new functionality and referring to the older way of doing things as “legacy”, with the promise of going back “later” to update this older code.

The only problem here is if this “legacy” code is still being used you still need to maintain it along with its dependencies.Before you know it, you’ve essentially doubled the amount of work as well as restricting yourself in the future, as every new thing you add may need to be compatible with this “legacy” code you still have lying around.

This is not a new story by any means, but its ramifications and pitfalls are well documented, and many have experienced this pain first-hand. To mitigate this at Cytora, we decided to separate application-specific code from reusable code using a well-known package called Lerna.

This library allowed us to organise our codebase by allowing us to create independent, single responsibility packages designed to fulfil a specific role regardless of the context they are used.

This means we can abstract away commonly used or “boilerplate” code into individual modules ready to be consumed by all our frontends. We also went a step further with this, setting up a CI/CD process that handles automatic versioning and publishing to our internal private repository ready to be used by each one of our frontends.

The development experience was improved because of this and it freed the frontend team to make key changes in internal packages at will — but we didn’t stop there. As with most modern web applications, we had to ensure the application we built matched our brand, both in style and feel.

Building out the component library

Previously we used a mixture of LESS, SASS, and inline styles in our applications which were sufficient for what we were building. Ordinarily, inline styling is generally discouraged because you cannot do things like pseudos and media queries without involving some sort of JavaScript. These things are very important if you want your application to be responsive.

However, with the new requirement of centralising our styling across all our frontends, we needed to create a UI component library which again could be consumed by all our frontends, rather than using a mixture of three approaches to style our applications.

To accomplish this, we decided to use Material-UI as a base design language due to its maturity as well as the variety of pre-made components and combined it with styled-components to allow us to skin these components with our brand style and colours.

Our UX team provided all the wireframes for our components including different states such as hover, focus, active, etc. It it was our team’s responsibility to convert these designs into usable, pixel-perfect components via styled-components.

Using this library meant styles become an integral part of the component, not something you add later, making reusing and applying styles a breeze. Styling wasn’t the only key consideration when we were scoping the requirements for the UWP.

The collection of micro-frontends we have were focused on a singular task, making things such as state management easy to do using React hooks. With the UWP it was very clear we would need a more robust way to manage state across the application.

Choosing how to do state management

State management is one of the most fundamentally important decisions you can make when developing scalable, enterprise web applications. Generally speaking, you literally cannot afford to get it wrong, as to do so and having to switch to another library, will take you a lot of time, and we all know the old adage…

Previously Facebook (the creators of React) introduced hooks, particularly the `useState` hook which allows you to store small bits of state. In recent times we have seen the emergence of Recoil, a new state management library by the same author, which is intended, in their own words, to be “minimal and reactish”. You can also see some notable entries like “reactn” to name a few.

It’s exciting to see these new entries into the scene however it’s equally important to think about long-term support and maturity. While the newer kids on the block have a lot going for them, there continues to be a single library that has clear dominance in the state management “market”, not just in React but in other UI libraries too — Redux.

We knew that our state was going to change often, complex data structures would exist in terms of risk data, and multiple components would depend on these states.

From this using React in-built state management was out of the question from a global state management perspective. We would instead use hooks to handle small, localised state not needed elsewhere and use Redux to manage global state.

To help with this we created helper packages to abstract away any complexities in Redux, allowing our main product and micro-frontends to benefit from a consistent way to manage state.

This provided further benefits because now we had a unified approach on how we manage state in the frontend space, further closing the knowledge gap between different projects.

A developer could jump from one codebase to another with ease, speeding up productivity overall. We did a few things in this area to speed things up and automate as much as possible.

Improving the developer experience

There is a saying that mixed project standards can be worse than no standards at all! It’s something that happens naturally in any organisation that has been around for a while.

People have different styles, technologies change, new approaches are adopted and very easily you can end up with multiple coding patterns spread across your organisation.

This, of course, affects interoperability, slowing down development as you need to “learn” a project before you can be effective at it. Because of this, we decided to unify code standards across all frontends using tools such as ES-Lint & Prettier.

They work by setting specific rules, perform static analysis on the code, and automatically fixing issues. This meant our projects began converging around a single standard.

Augmenting this with a clear set of coding and patterns guidelines, such as exclusive use of functional programming, meant we could not only increase the speed of development but also reuse code across multiple projects much easier.

With a focus on CI/CD across the frontend space, testing was another key area to ensure we deliver high-quality features into the production environment.

Ensuring the reliable delivery of features

Along with static code analysis, unit and integration tests are an essential part of how we ensure quality at Cytora. JEST is a great testing platform, with the ability to adapt to any JavaScript library or framework which made it perfect for use within our React ecosystem.

At Cytora we use React Testing Library combined with JESTDOM to write unit tests, and BrowserStack for our integration tests. Given JEST’s inbuilt support for code coverage, powered by Istanbul, we can easily integrate all these metrics directly into our CI/CD platform. This made it very easy to set thresholds on code coverage, quality and standards.

Of course, after the application has gone live is where things get interesting. I’ve always thought the best QA’s in the world is the public at large — no joke! I can’t count the number of times I’ve seen someone using an application in ways you would have never imagined or designed. This, of course, is a rich area for unexpected behaviour and errors which are better found sooner rather than later…

Integrating with third-party providers

Looking at solutions to this issue there are two paths you can take: build the solution yourself, or get something off the shelf. It’s always going to be a balance between the resources you currently have and what needs to be done and implementing third party providers was the perfect balance for us.

We went for Sentry to provide application monitoring to our frontends and help us diagnose, fix, and optimise code way before a support ticket is raised. This means we are aware of how the application is performing in the wild and can address issues as soon as they creep up, making us extremely responsive to customer needs.

LaunchDarkly is also another tool we use in multiple contexts. At its core, it is a feature flagging tool meaning we can turn features on and off for different audiences as we pleased. It was also critical to our CI/CD approach because it allows us to ship features in progress and turn them off in a production environment until they are ready.

What’s next?

Working on a greenfield project like the Underwriting Productivity Suite has been both interesting and challenging. There is a certain air around ensuring you are making the correct decisions to support future endeavours which adds to the planning, but the experience has been fantastic and rewarding.

What we’ve been able to build so far is a modern, fast, and disruptive application; we truly are building the future of commercial insurance. Watch this space.

For more detail on the Underwriting Productivity Suite, visit the Cytora website.