A Casual Dive into Monorepos with NPM Workspaces: Simplifying Your Project (Without the Headaches)
Alright, let's talk monorepos and npm workspaces—two things that sound complicated but are actually pretty cool once you get into them. If you're like me and like to keep things organized but hate unnecessary friction (we're builders, not bureaucrats), then you might want to think about using npm workspaces to manage your projects. It’s efficient, minimal, and once you set it up, it’s a bit like having a really slick filing system where you actually know where everything is (imagine that!).
First Off, What Is a Monorepo?
If you’ve been in the dev world for a bit, you’ve probably heard this buzzword floating around. A monorepo is basically one big repository where you keep multiple projects. So, instead of having a bunch of smaller repos for your frontend, backend, infrastructure, etc., you just throw them all into one. Sounds chaotic, right? Surprisingly, it's not. It’s like having all your tools in one toolbox instead of scattered across the garage—you save time and reduce clutter.
In my case, I might have my Next.js frontend, a Node.js backend, and some infrastructure configuration, all neatly organized in a single monorepo. The trick to making this work without it turning into a mess? NPM workspaces.
What’s NPM Workspaces?
Glad you asked. NPM workspaces is npm's way of letting you manage multiple packages or projects inside one repo. If you’ve used Lerna before, think of npm workspaces as Lerna’s more chill cousin—doesn’t try to overcomplicate things but still gets the job done. You use it to organize, share dependencies, and run scripts across different parts of your monorepo.
So, for example, if you’ve got your frontend and backend living side by side in the same repo, npm workspaces lets you run npm install
in one place and share dependencies between those projects, rather than having duplicate copies floating around (no one needs that kind of drama).
Setting Up a Basic Monorepo with NPM Workspaces
Alright, let’s break it down. Setting up npm workspaces is actually straightforward, but let me walk you through it so we don’t hit any snags.
Create a New Directory for Your Monorepo: Let’s assume you’ve got a fresh directory for your project.
mkdir my-monorepo cd my-monorepo npm init -y
This gives you your root
package.json
—nothing fancy yet, but it’s about to get interesting.Define Your Workspaces: Next, open up that
package.json
and add aworkspaces
field. This is where you tell npm what subdirectories hold your separate projects.{ "name": "my-monorepo", "private": true, "workspaces": [ "frontend", "backend", "infra" ] }
Here, I’ve got
frontend
,backend
, andinfra
as my workspaces. Each one of those will be its own little project (we’ll get there in a sec). Also, notice that"private": true
is set—this prevents you from accidentally publishing the whole thing to the npm registry. You’re welcome.Initialize the Individual Projects: Now, let’s initialize the individual workspaces. First, create the directories:
mkdir frontend backend infra
Then, inside each one, run
npm init -y
to create separatepackage.json
files for each project. For example:cd frontend npm init -y
Repeat that for
backend
andinfra
. Now each workspace has its ownpackage.json
but they’re all part of the same big happy family (the monorepo).Sharing Dependencies: Now, here’s where npm workspaces shines. Say both your frontend and backend need
lodash
. Instead of installing it twice, you can install it once from the root:npm install lodash
Npm will handle the rest, deduplicating dependencies and making sure everyone gets what they need. No more "why do I have 300 copies of React" moments.
Running Scripts Across Workspaces: This is where things get interesting. Let’s say you’ve got a
build
script in both your frontend and backendpackage.json
files. With npm workspaces, you can run that script across both projects with one command:npm run build --workspaces
Or, if you just want to build the frontend:
npm run build --workspace=frontend
Pretty slick, right?
But Wait, There's More: Managing Permissions
Now, if you’re like me, you might start thinking about security—especially if your backend has sensitive stuff going on (maybe you’re CRUD-ing from a database, or handling API keys). The last thing you want is your frontend having unnecessary permissions to poke around where it shouldn't.
In a more advanced setup, you can fine-tune permissions. But for now, keeping things simple: make sure your backend has its own .env
file, and don’t accidentally expose those variables to the frontend. A good old .gitignore
and some environment variable hygiene go a long way here.
A Quick Word About Overcomplicating Things
Look, it’s easy to fall into the trap of overcomplicating your monorepo—especially when you start adding things like CI/CD, Docker, or whatever shiny new thing catches your eye. My advice? Start small, get a feel for workspaces, and then build from there. Maybe you don’t need to worry about infrastructure code in infra
just yet. Maybe your frontend and backend are all you need for now.
By starting with just the basics—organizing your projects, sharing dependencies, and running scripts across workspaces—you’re already making life a lot easier. The fancy stuff can come later.
Closing Thoughts
So there you have it. A monorepo setup with npm workspaces is simple, efficient, and helps you avoid the chaos of managing multiple repos. Whether you're managing a Next.js frontend, a Node.js backend, or some infrastructure magic, npm workspaces keeps things neat and friction-free.
It's like cleaning out your junk drawer—you know it needs to be done, but once it’s organized, everything just works better.
If you’re curious about diving deeper into monorepos or need to simplify your current setup, give npm workspaces a try. You’ll thank yourself later when your project scales and everything is still tidy. Plus, you might just find that building complex things doesn’t always have to be complicated.
Subscribe to my newsletter
Read articles from Benjamin Temple directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by