Case study · Frontend platform

Rebuilding the foundation 150+ apps ship on.

A platform-wide modernization of Mindtickle's frontend build: Node 12 → 22, Yarn 1.22 → Yarn 4 (PnP), and Module Federation v1 → v2 — unified behind one central config so every repo shares a modern, fast, secure build.

Role: Designed the build system Platform-wide · ~150 repos Node 22 · Yarn 4 PnP Module Federation v2
Build artifact size — before vs after28 apps · staging → ux-refresh-perf
Before (Yarn 1 · Node 12) After (Yarn 4 · PnP · Node 22)
course-ui−93%
2487 MB
158 MB
kea-core−94%
2312 MB
134 MB
global-search-ui−93%
2299 MB
138 MB
get-support−91%
1633 MB
133 MB
ui-shell−85%
966 MB
136 MB
Docker/build artifacts, measured across 28 apps — a consistent 85–94% reduction.
~91%
Smaller build artifacts, across ~28 apps
2–3×
Faster CI — 12–35 min → under 10 min
~4×
Faster installs (Yarn 4 vs Yarn 3.6)
150+
Apps on one shared, modern foundation
01
The problem

A legacy build was throttling every frontend team.

Mindtickle's frontend isn't one app — it's 150+ micro-frontends across ~50 repos. They all sat on an aging foundation, and it showed everywhere at once:

Slow CI/CD — 12–35 minutes to build and deploy per environment. Legacy & insecure — Node 12 (end-of-life) with high-vulnerability dependencies. Fragmented tooling — a mix of npm and Yarn 1.22. And bloated artifacts — Docker images of 1.5–2.5 GB per app. Every team paid this tax on every deploy.

02
The revamp

Modernize the toolchain — once, for everyone.

Rather than let 150 repos drift on their own, I designed one modern foundation and unified it behind a central config package every repo extends.

Runtime
Node 12 → 22
V8 · Maglev
+
Packages
Yarn 1 → 4
Berry · PnP
+
Federation
MFE v1 → v2
dynamic remotes
+
Config
One source
frontend-configs

Yarn 4 (Berry) + Plug'n'Play

No node_modules, ~4× faster installs than Yarn 3.6, less disk, faster startup, and Hardened Mode for lockfile / metadata integrity — plus cross-team dependency sharing through PnP.

Module Federation v1 → v2, and faster CI

Dynamic remoteEntry resolution with standardized Dockerfile + naming → "build once, deploy anywhere." Paired with parallel Webpack builds and component-driven CI that rebuilds only what changed.

One central config — @mindtickle/frontend-configs

A single extendable source for webpack / babel / TS / eslint / prettier / relay / docker / semantic-release, consumed by every repo (extends @mindtickle/frontend-configs). Itself on Yarn 4 PnP. This is the foundation the one-click dev setup later automated onboarding onto.

03
Receipts

Measured, not guessed.

Build times tracked in Grafana, page-load in Datadog RUM, and DORA metrics across the board. The headline: build artifacts ~91% smaller and CI 2–3× faster. On payload, most pages got dramatically lighter — and I'll show the ones that didn't, too.

JavaScript transferred per page — change after revamphonest: 2 remotes grew mid-migration
Lighter (reduced) Heavier (grew — mid-migration remotes)
email-template-picker
−92%
collaborator-management-ui
−52%
announcement
−50%
invite-track-ui
−48%
global-search
−39%
kea-core
−33%
course-ui
−25%
get-support
−17%
ui-shell
+30%
ui-auth
+43%
← heavier0%lighter →
~91%
Smaller build artifacts (85–94% across 28 apps)
2–3×
Faster CI — 12–35 min → < 10 min
119 → 19
CSS style tags in the DOM (training page)
Weekly → daily
Deployment frequency
High → minimal
Dependency vulnerabilities
DORA
Tracked in Grafana + Datadog RUM

Artifact and payload figures measured staging → ux-refresh-perf across ~28 apps. A couple of remotes (ui-shell, ui-auth) grew while mid-migration — shown here rather than hidden.

Keep reading

I modernized the foundation — then made it one command.

Next case study
One-Click Dev Setup →