exile.watch architecture
10 min read
Last updated
10 min read
Last updated
Seven repositories, over ten packages, one Chrome extension, and one user-facing website... all managed by one person.
Wait, wait, wait... How many repositories and packages are there again?
For... one user-facing website? Surely there must be some micro-frontends because otherwise, this seems like a completely overengineered solution.
No. There are no micro-frontends. In fact, the user-facing website doesn't even have ten pages.
You read it correctly. This modularity is by design. But is this approach beneficial?
Let's dive in.
I’ve been sticking with React for a good while now (7 years and counting), and honestly, it just fits like a glove for what I need to do. Picking it was pretty much a no-brainer for me.
Does React have flaws? Sure, as do other tools. However, I won't be delving into those here.
Given the project's needs, SEO (Search Engine Optimization) was a significant consideration. exile.watch was initiated in 2021, and while I don't recall if SEO was a strong selling point for React at that time, I do remember that Next.js was particularly effective at satisfying SEO crawlers.
At the time, Next.js offered the server-side rendering capabilities with the least developer experience friction.
I'm a big fan of the Bulletproof React repository for its clean and concise approach to project structure. This is my goal whenever I start a new React/Next.js project, and that's exactly what I aimed for with exile.watch in 2021.
The development of exile.watch was on full throttle.
However, with the introduction of the Expedition league in the Path of Exile game...
I lost all interest in the game, and consequently, my motivation to continue with exile.watch diminished.
End of January 2024 enters the chat. Being let go from the company due to bankruptcy I developed an itch to learn Lerna.
During my time at the company, we extensively levereged Lerna. I was part of the Engineering Productivity team, and over time we created a stellar frontend architecture that I will always aim to achieve, as long as resources (people and time) will allow.
This is what sparked my comeback to exile.watch after a three-years hiatus, given the "dependency mess" I had left behind and the breakdown to smaller projects and packages.
I decided to use exile.watch as my own sandbox for learning.
Lerna is a fast, modern build system for managing and publishing multiple JavaScript/TypeScript packages from the same repository.
Monorepos let you develop multiple packages in the same repository, which is fantastic for productivity. You can share code, establish clear ownership, and have fast unified CI.
To use monorepos well, you need a good monorepo tool, and Lerna is exactly that. Lerna is fast, widely used, and battle tested.
So, I've got React, Next.js, Lerna... components, hooks, some dependencies... Some dependencies.
29 dependencies, 49 devDependencies. That's... A LOT.
I have waaay more devDependencies than dependencies, so let's address this first.
Given what devDependencies are all about, it made sense to kick things off by tackling the build tools. This meant setting up my first Lerna monorepo to manage just that.
First up, creating @exile-watch/typescript-config to ditch 10 TypeScript-related packages.
Next, swapping out individual code quality tools for @exile-watch/biome-config, which axed another 11 packages.
And planning to swap out Storybook for @exile-watch/storybook-config, shedding another 7 packages in the process.
Seeing the pattern yet?
Same story with the dependencies.
Initially, I didn't lean on any UI library, which meant my themes and icons were kinda all over the place. That sparked the creation of @exile-watch/writ, our Lerna monorepo design system, housing @exile-watch/writ-react and @exile-watch/writ-icons packages.
PS: Here is the current list of dependencies for comparison
And here I am, two weeks after diving back into the project.
7 repositories, 10+ packages, 1 chrome extension and 1 user facing website.
But... how do you even keep track of all this?
Simple answer: Dependabot group updates.
I wrote a separate post about Dependabot here.
For now, just know Dependabot is like that reliable buddy doing all the heavy lifting for you—keeping everything updated without you breaking a sweat.
You can see it in action here.
Let's wrap this up with some pros and cons based on what I've been through.
Everything's modularized: Each Lerna monorepo, package, and consumer app knows its lane, focusing sharply on its defined scope
Jump-starting new projects is a breeze since everything’s pre-configured, letting other team members hit the ground running with feature development
Unified updates mean when something changes, it hits the whole org at once—keeping everyone on the same wavelength
Frequent rotations? Easy. Moving between projects is smooth since you’re always familiar with the setup
The development approach is opinionated, guiding the team with clear rules to follow
Thinking of kicking off a new project? This architecture might feel like swatting a fly with a sledgehammer—total overkill unless you’re in it for the learning curve.
Got a couple of frontend teams already? Great! This might be time to think about bringing things together with a centralized solution
Still on the fence? Remember what I said about sticking to Bulletproof React for simplicity’s sake
Resource drain alert: Getting all this up and running eats up time and people—usually needing a dedicated person or a small squad focused on R&D and pushing engineering productivity to new heights
Update fatigue is real. Without Dependabot finely tuned, your team might get bogged down with constant updates, shifting focus from feature delivery to keeping up with the latest package versions
Author: Sebastian Krzyżanowski About exile.watch: https://docs.exile.watch/ Github: https://github.com/exile-watch Visit https://exile.watch/ to experience it first hand