Ravelin’s Front-End Tech Stack

Tim Phillips
Ravelin Tech Blog
Published in
7 min readSep 22, 2021

--

This article presents a snapshot of Ravelin’s front-end technology in 2021.

For some context, the front-end team at Ravelin is responsible for building the client-side of our fraud technology platform. Our chief focus is a dashboard web application that serves as the client-facing portal into Ravelin’s system.

A sample customer profile in the dashboard

Our dashboard is used by our clients’ Fraud Analysts and Fraud Managers to monitor and gain insight into Ravelin’s decisions on fraud and payments. There’s a lot that goes into it — including data visualisations (e.g. network graphs, timelines, heatmaps), customer profiles, reporting, auditing, and tailored system configuration.

Our goal is to enable our users to work more effectively and make their lives easier, so we’re continually challenged with improving our user experience, and along with it, our technology platform. We’ve grown rapidly over the last couple of years and we recently achieved a milestone of over a million page views a month.

At a high level, our web applications are built with TypeScript and React — but there are many other tools, libraries and services being used under the hood. The goal of this article is to highlight the key technologies we use, but this doesn’t cover everything. We’ve adopted some of these tools recently, while others we’ve used for years. We’re a small team and we have a cautious and pragmatic approach to adopting new technology.

Read on!

JavaScript Libraries

TypeScript
We’ve been using TypeScript at Ravelin for over five years and we currently use it for all of our front-end scripting.

Building large-scale web applications with JavaScript is challenging because it’s an interpreted, loosely typed language. Many common JavaScript errors occur because the language doesn’t provide any way to enforce type safety — for example, errors such as these:

  • Passing a number argument to a function that expects a string parameter
  • Renaming an object property, but forgetting to rename the property everywhere where it is used throughout the codebase

TypeScript aims to address these problems by adding static types to JavaScript. Using TypeScript helps us catch errors earlier in development because the TypeScript compiler identifies errors at compile time rather than at runtime in the browser. TypeScript also allows for an enhanced development experience in IDEs because the type information can be used to power automated code refactoring and intellisense.

React
Over the course of 2020 and 2021, we migrated our web framework from AngularJS to React. AngularJS was reaching the end of its Long Term Support and we needed to either upgrade to Angular or try something new. After a thorough evaluation of Angular, Vue, and React, we decided to adopt React. The migration was a big project that involved converting over 70,000 lines of code to the new framework.

We built our new dashboard using functional React components and hooks, with some minimal use of Context as well. Notably, we do not use a third-party state management library such as Redux or MobX. We’ve found that the built-in state management capabilities of React hooks work well for our use cases (we don’t have a lot of application-wide state to manage, so we’re able to keep state quite local to where it is used).

Unlike fully-featured frameworks like Angular, React is a bare-bones library that only handles rendering the UI. So, we rely on a few other third-party libraries to fill in some gaps:

Axios
Axios
is a promise-based HTTP library for performing HTTP requests. It improves upon the browser’s built-in XMLHttpRequest API with extra features such as timeouts, cancellation, and serialisation/deserialisation of request data.

We also use axios-mock-adapter for mocking API requests in tests.

Chart.js + D3
Most of the data visualisations on our dashboard are built with Chart.js. It’s easy to work with and produces attractive and lightweight canvas visualisations.

Analytics report built with Chart.js
Analytics report built with Chart.js

We also use D3.js for more customised and interactive visualisations. In particular, D3 powers our Connect graph. It’s a powerful library but it has a steep learning curve; we’d only recommend using it for very specialised use cases.

Connect graph built with D3
Connect graph built with D3

Moment
Moment.js
is a library that simplifies working with dates and times in JavaScript. Our users access the dashboard from over fifty countries around the world, so we regularly have to deal with timezone and localisation issues.

Moment is now considered a legacy library. There are likely smaller and more flexible alternatives if starting fresh with a new project.

Pusher
We use Pusher for realtime notifications within our applications. For example, we show an alert in the UI when two different users are viewing the same customer profile at the same time.

Storybook
We maintain a Storybook UI library with isolated examples of the “building block” React components we use to create our applications. This component library helps drive consistency across the product, and also improves developer productivity since the examples are backed by real code.

Testing

Jest
Jest is the recommended testing framework for React applications. It integrates well with jsdom, which allows for testing React components in a simulated browser environment.

We also use jest-dom to extend Jest with extra test matchers for DOM attributes. For example, we can use assertions like toBeEnabled and toBeDisabled to more intuitively test if a button is enabled or disabled.

React Testing Library
We write tests for React components using React Testing Library. Its guiding principle is: “the more your tests resemble the way your software is used, the more confidence they can give you.” The library provides utility functions to simulate using components in the same way a real-world user would (clicking on buttons, submitting forms, etc).

Cypress
Cypress runs our end-to-end integration tests. We run our integration test suite as part of the release pipeline, as well as on an automated schedule.

Linting

Prettier
Prettier
is an opinionated code formatter. All of our TypeScript code is automatically formatted with Prettier via a husky pre-commit git hook. This enforces a consistent style across the team and effectively eliminates style discussions from code reviews — a huge time saver!

ESLint
ESLint
is a popular static code analysis tool for JavaScript. It identifies common errors, such as unreachable code, infinite loops, and so on. Many of the errors can be automatically fixed.

It’s customisable and there are many third-party plugins maintained by the community. We use typescript-eslint which adds support for TypeScript-specific rules.

stylelint
We use stylelint to lint our CSS. It catches common errors and helps enforce conventions across the codebase. The standard configuration works well out of the box and we haven’t found the need to customise it too much.

CSS

We have a utility-first approach to CSS. Internally we maintain a customised version of Basscss, which provides common low-level CSS rules. We’re able to style most components using our utility classes, but occasionally we’ll create specialised classes to handle unique cases.

One library that’s worth mentioning is classnames. It makes dynamic and conditional CSS classes simpler to work with in React components.

Build

Gulp
Gulp
is the backbone of our build pipeline. It’s a task runner that we use to automate tasks in our workflows. For example, we have a Gulp task to create a production-ready build of our web application.

webpack
webpack
is a module bundler that converts our TypeScript source code into the static assets that are served to the browser.

PostCSS
We package our CSS using PostCSS. This tool merges all our CSS files into a final bundle, and also optimises the code for cross-browser compatibility (for example, vendor prefixes are automatically added with the Autoprefixer plugin).

CircleCI
CircleCI is the platform we use for continuous integration. Every code change triggers an automated test, build, or deployment task in CircleCI.

Monitoring

Mixpanel
Mixpanel
is an analytics tool that enables us to capture data about how our users use our products. For example, we use these analytics to determine which product features are most popular and which features are rarely used.

We also use Mixpanel to gain insight into metrics such as the browser versions or screen resolutions that are most commonly used by our users.

Sentry
Sentry
is an error monitoring platform. An issue is automatically created in Sentry whenever an unhandled JavaScript error occurs in the dashboard, along with a stack trace and metadata about the error. The platform also allows us to configure notifications so that we’re alerted when a new error occurs.

Collaboration Tools

We use Slack, Notion, and Google Workspace.

Our code is hosted on GitHub. We require that all pull requests are code reviewed by another developer before they’re merged. We don’t have dedicated QA at Ravelin — this encourages everyone on the team to focus on quality across their daily tasks.

Summary

Hopefully this article provided some insight into our front-end technology at Ravelin. Check out our careers page if you’d like to join us in our fight against fraud.

--

--