I have several React+Next.js projects; I have some code that I’d like to share among these projects. For example, I bought a website template, which I’d like to reuse across different websites. Also, I have some util functions (such as Google Analytics tracking) that I’d like to reuse.
This article shows the minimum setup to meet the requirements above. https://monorepo.tools/ unfortunately does not meet what I need because it assumes that people want the heavy duty distributed solution. But I don’t want that; I just want to reuse code locally.
Directory structure
The key is to use NPM workspaces. Here is the directory structure:
- monorepo-template/
- package.json
- packages/
- project1/ (T3 stack https://create.t3.gg)
- package.json
- ...
- shared/
- package.json
- website-template/
- static/
- images/
project1
is a T3 project; it will act like a standalone T3 project with our setup. shared
is a project where we share code to other projects. All of them are NPM workspaces.
The key setups
https://github.com/junhe/monorepo-template has the complete template. This DIFF shows the key setup. We explain the key setups here.
monorepo-template/package.json
has the following contents. It sets up the workspaces.
{
"private": true,
"workspaces": ["packages/*"]
}
monorepo-template/packages/shared/package.json
has the following contents, which configures the shared package. We put the reusable code here.
{
"name": "shared",
"version": "1.0.0",
"main": "index.tsx",
}
monorepo-template/packages/shared/index.tsx
has the following contents.
export function greet() {
return "Hello from shared!";
}
Create project1
by doing the following. Use project1
as the project name for the t3 app. Do not initialize the Git repo because we will soon make monorepo-template
the Git repo; that’s the whole purpose of this article.
cd monorepo-template/packages/
npm create t3-app@latest
Add the following contents to monorepo-template/packages/project1/package.json
:
"dependencies": {
"shared": "1.0.0"
},
"scripts": {
"copy-shared": "rm -rf public/shared/website-template && mkdir -p public/shared/website-template && cp -r ../shared/website-template/static public/shared/website-template/",
"link-shared": "rm -rf public/shared/website-template && mkdir -p public/shared/website-template && ln -s ../../../../shared/website-template/static public/shared/website-template/static",
"predev": "npm run link-shared",
"prebuild": "npm run copy-shared"
},
Note that, for local development, we use soft link to link the files from shared
to project
, so all the changes in shared
will be immediately available in project1
. But for build, we copy the files because in Vercel you can’t link. Please go to https://github.com/junhe/monorepo-template to see what is in monorepo-template/packages/shared
.
Test it
git clone git@github.com:junhe/monorepo-template.git
cd monorepo-template/packages/project1
npm install
npm run dev
Open http://localhost:3000/. You should see the following, which are code and image from shared/
.

Deploy it
Go to https://vercel.com/, follow the usual steps to deploy. Everything should be straightforward; but make sure the settings are as follows. Root directory should be packages/project1
.

The app is deployed at https://monorepo-template-project1.vercel.app/.