Composite UI with Design System and Micro Frontends

The story of how we modernized an existing application and its design by using desing systems and micro frontends.

Reimagining Our UI: From Utility to Core Component

Recently my team started thinking about replacing our UI in our system. The core of our system consists of several modules that ingest, process and publish data from GPS trackers. Historically, UI wasn't a core context in our system; it functioned as a configuration and observability utility for developers and a few end users. You could remove it, and the system would still work and generate value. Over the years, UI context gained importance. We now want to modernize it and align its design with other applications.

Considering Context Ownership in UI Development

One of the considerations that we are debating is if we can make context own parts of the UI concerned directly with it. For example, can we make context dealing with signal sources publish UI concerning its configuration? We can accomplish that by making our UI context a shell for micro frontends published by different contexts. To make UI consistent across all micro frontends, we could build a design system published and consumed by them.

Proving the Concept: A Step-by-Step Approach

This post will detail the PoC I've built to prove the viability of this approach. It will consist of the following steps:

  1. Building a design system - a react component library that can be reused across different micro frontends. We will use tailwind as a seed for our design system. We will configure the storybook for testing and documentation. We will export it as a package.

  2. Consuming design system in micro frontends. For all build and packaging needs, we will use webpack 5. We will give micro frontends the ability to display as a standalone application or embedded in a shell application.

  3. Composing micro frontends in a shell application.

To make examples more relatable for readers, we will change the domain. Somehow equivalent to our situation would be building an application for improving fitness and wellness. We can imagine an application like this would consist of the following contexts: nutrition tracking, exercise tracking, meal planning and recipe management. Each of these contexts could live independently; however, it will generate additional value when combined.

The goal of this PoC is to have 4 micro frontends, shell application, and storybook (design system) run on separate ports. As on the screenshot below.

We should be able to run all micro frontends composed in a shell application and separately in stand-alone mode. Additionally, storybook, documentation for our design system should also run separately.

Access the Source Code

You can find source code for the final solution in this repository https://github.com/belczyk/blog-examples-desing-system-mf.

Exploring Different Approaches to Micro Frontends

Before we jump into the code, let me say that this is not the only approach for micro frontends and design systems that you can choose. For example, instead of agreeing on one frontend framework and publishing components, you could publish only style sheets/design tokens and allow teams to select the frontend framework that they want to use.

There are different ways you can integrate your micro frontends. We will explore only one way (via JavaScript inclusion). See the "Micro Frontends" blog post on Martin Fowler's blog to explore options.

 

Blog 7/16/21

Building A Shell Application for Micro Frontends | Part 4

We already have a design system, several micro frontends consuming this design system, and now we need a shell application that imports micro frontends and displays them.

Blog 7/14/21

Building and Publishing Design Systems | Part 2

Learn how to build and publish design systems effectively. Discover best practices for creating reusable components and enhancing UI consistency.

Blog 7/15/21

Building a micro frontend consuming a design system | Part 3

In this blopgpost, you will learn how to create a react application that consumes a design system.

Blog 9/27/22

Creating solutions and projects in VS code

In this post we are going to create a new Solution containing an F# console project and a test project using the dotnet CLI in Visual Studio Code.

Blog 6/16/23

CSS :has() & Responsive Design

In my journey to tackle a responsive layout problem, I stumbled upon the remarkable benefits of the :has() pseudo-class. Initially, I attempted various other methods to resolve the issue, but ultimately, embracing the power of :has() proved to be the optimal solution. This blog explores my experience and highlights the advantages of utilizing the :has() pseudo-class in achieving flexible layouts.

Blog 5/17/23

Introduction to Functional Programming in F# – Part 10

Discover Agents and Mailboxes in F#. Build responsive applications using these powerful concurrency tools in functional programming.

Blog 3/22/23

Introduction to Functional Programming in F# – Part 8

Discover Units of Measure and Type Providers in F#. Enhance data management and type safety in your applications with these powerful tools.

Blog 11/9/23

Process Pipelines

Discover how process pipelines break down complex tasks into manageable steps, optimizing workflows and improving efficiency using Kanban boards.

Blog 5/20/22

My Weekly Shutdown Routine

Discover my weekly shutdown routine to enhance productivity and start each week fresh. Learn effective techniques for reflection and organization.

Blog 4/28/23

Creating a Social Media Posts Generator Website with ChatGPT

Using the GPT-3-turbo and DALL-E models in Node.js to create a social post generator for a fictional product can be really helpful. The author uses ChatGPT to create an API that utilizes the openai library for Node.js., a Vue component with an input for the title and message of the post. This article provides step-by-step instructions for setting up the project and includes links to the code repository.

Blog 5/18/22

Introduction to Functional Programming in F#

Dive into functional programming with F# in our introductory series. Learn how to solve real business problems using F#'s functional programming features. This first part covers setting up your environment, basic F# syntax, and implementing a simple use case. Perfect for developers looking to enhance their skills in functional programming.

Blog 10/21/20

Consistency and Aggregates in Event Sourcing

Learn how we ensures data consistency in event sourcing with effective use of aggregates, enhancing system reliability and performance.

Blog 7/14/23

Event Sourcing with Apache Kafka

For a long time, there was a consensus that Kafka and Event Sourcing are not compatible with each other. So it might look like there is no way of working with Event Sourcing. But there is if certain requirements are met.

Blog 7/21/20

Understanding F# applicatives and custom operators

In this post, Jonathan Channon, a newcomer to F#, discusses how he learnt about a slightly more advanced functional concept — Applicatives.

Blog 10/27/21

Isolating legacy code with ArchUnit tests

Clear boundaries in code are important ... and hard. ArchUnit allows you to capture the structure your team agreed on in tests.

Blog 11/14/23

Part 2: Data Analysis with powerful Python

Analyzing and visualizing data from a SQLite database in Python can be a powerful way to gain insights and present your findings. In Part 2 of this blog series, we will walk you through the steps to retrieve data from a SQLite database file named gold.db and display it in the form of a chart using Python. We'll use some essential tools and libraries for this task.

Blog 3/10/21

Introduction to Web Programming in F# with Giraffe – Part 1

In this series we are investigating web programming with Giraffe and the Giraffe View Engine plus a few other useful F# libraries.

Blog 3/11/21

Introduction to Web Programming in F# with Giraffe – Part 2

In this series we are investigating web programming with Giraffe and the Giraffe View Engine plus a few other useful F# libraries.

Blog 3/12/21

Introduction to Web Programming in F# with Giraffe – Part 3

In this series we are investigating web programming with Giraffe and the Giraffe View Engine plus a few other useful F# libraries.

Blog 11/12/20

Announcing Domain-Driven Design Exercises

Interested in Domain Driven Design? Then this DDD exercise is perfect for you!