Personal Monorepo Setup with Vercel

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/.

Leave a Reply

Your email address will not be published. Required fields are marked *