DEV Community

Rahul Vijayvergiya
Rahul Vijayvergiya

Posted on • Edited on

How to Setup monorepo with Turborepo

In this guide, we will create a monorepo using TurboRepo, integrating React, Express, and PNPM. We will also include shared code for UI components and functions. The process involves several steps. Here’s a detailed guide to help you set up this project:

Step 1: Initialise the Monorepo

1. Install PNPM (if not already installed):

npm install -g pnpm
Enter fullscreen mode Exit fullscreen mode

2. Create the Monorepo Directory:

mkdir turbo-monorepo
cd turbo-monorepo
Enter fullscreen mode Exit fullscreen mode

3. Initialise the Monorepo:

pnpm init
pnpm install -D turbo
Enter fullscreen mode Exit fullscreen mode

4. Setup Turbo Repo Configuration: Create a turbo.json file in the root directory:

{
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**"]
    },
    "lint": {},
    "test": {}
  }
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Setup Workspace and Packages

1. Create Project Directories:

mkdir -p apps/client apps/server packages/ui packages/utils
Enter fullscreen mode Exit fullscreen mode

2. Configure pnpm-workspace.yaml:

packages:
  - 'packages/*'
  - 'apps/*'
Enter fullscreen mode Exit fullscreen mode

Step 3: Initialise Client (React) and Server (Express) Projects

1. Client (React):

cd apps/client
pnpm create vite . --template react
pnpm install
cd ../..
Enter fullscreen mode Exit fullscreen mode

2. Server (Express):

cd apps/server
pnpm init -y
pnpm add express
touch index.js
cd ../..
Enter fullscreen mode Exit fullscreen mode

3. Add Basic Express Server Code in apps/server/index.js:

import express from "express"
import { greet } from "@shared/utils"
const app = express()
const port = 3000
app.get("/", (req, res) => {
  res.send(greet(" This is greeting from common code"))
})
app.listen(port, () => {
  console.log(`Server is running at http://localhost:${port}`)
})
Enter fullscreen mode Exit fullscreen mode

Step 4: Add Shared Packages

1. UI Shared Package Setup:

cd packages/ui
pnpm init -y
touch index.js
cd ../..
Enter fullscreen mode Exit fullscreen mode

2. Change Name property of package.json to @shared/ui

{
  "name": "@shared/ui",
  "version": "1.0.0",
  "description": "",
  "main": "index.jsx",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}
Enter fullscreen mode Exit fullscreen mode

3. Example Shared Component in packages/ui/index.js:

import React from "react"
export const Button = ({ label }) => {
  return (
    <>
      <button type="reset" value="Reset" style={{ background: "red" }}>
        {label}
      </button>
    </>
  )
}
Enter fullscreen mode Exit fullscreen mode

1. Setup Shared Utils Package:

cd packages/utils
pnpm init -y
touch index.js
cd ../..
Enter fullscreen mode Exit fullscreen mode

2. Change Name property of package.json to @shared/utils

{
  "name": "@shared/utils",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "type": "module",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}
Enter fullscreen mode Exit fullscreen mode

3. Example Shared Function in packages/utils/index.js:

export const greet = (name) => {
  return `Hello, ${name}!`
}
Enter fullscreen mode Exit fullscreen mode

Step 5: Link Shared Packages

Link Packages: (Not sure: This may be not required )

pnpm add @packages/ui @packages/utils --filter @apps/client
pnpm add @packages/utils --filter @apps/server
Enter fullscreen mode Exit fullscreen mode

Step 6: Update package.json Scripts

1. Update Root package.json to add Script and workspace:

Note: Before this install concurrently: pnpm add -D concurrently

{
  "name": "turbo-monorepo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "private": true,
  "workspaces": [
    "apps/*",
    "packages/*"
  ],
  "scripts": {
    "build": "turbo run build",
    "lint": "turbo run lint",
    "test": "turbo run test",
    "start": "concurrently \"pnpm --filter @apps/server start\" \"pnpm --filter @apps/client dev\""
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "concurrently": "^8.2.2",
    "turbo": "^1.13.3"
  }
}
Enter fullscreen mode Exit fullscreen mode

2. Update Client to add @shared/utils and @shared/ui in package.json:

{
  "name": "@apps/client",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "lint": "eslint . --ext js,jsx --max-warnings 0",
    "preview": "vite preview"
  },
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "@shared/utils": "workspace:*",
    "@shared/ui": "workspace:*"
  },
  "devDependencies": {
    "@types/react": "^18.2.66",
    "@types/react-dom": "^18.2.22",
    "@vitejs/plugin-react": "^4.2.1",
    "vite": "^5.2.0"
  }
}
Enter fullscreen mode Exit fullscreen mode

3. Update Server package.json to add @shared/utils dependency

{
  "name": "@apps/server",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "type": "module",
  "scripts": {
    "start": "node index.js",
    "lint": "eslint . --ext .js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.19.2",
    "@shared/utils": "workspace:*"
  }
}
Enter fullscreen mode Exit fullscreen mode

Step 7: Configure ESLint/Prettier/ VSCode Workspace in project root

1. Install ESLint and Prettier:

pnpm add -Dw eslint prettier eslint-plugin-react eslint-config-prettier eslint-plugin-prettier
Enter fullscreen mode Exit fullscreen mode

2. Create ESLint Configuration (.eslintrc.json):

{
  "extends": ["eslint:recommended", "plugin:react/recommended", "prettier"],
  "plugins": ["react", "prettier"],
  "env": {
    "browser": true,
    "node": true,
    "es6": true
  },
  "parserOptions": {
    "ecmaVersion": 2020,
    "sourceType": "module"
  },
  "rules": {
    "react/prop-types": "off",
    "react/react-in-jsx-scope": "off",
    "prettier/prettier": [
      "error",
      {
        "endOfLine": "auto",
        "semi": false
      }
    ]
  },
  "settings": {
    "react": {
      "version": "detect"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

3. Create Prettier Configuration (.prettierrc.json):

{
  "singleQuote": false,
  "semi": false
}
Enter fullscreen mode Exit fullscreen mode

4. Setup VSCode Workspace : Create .vscode/settings.json:

{
  "editor.formatOnSave": true,
  "eslint.validate": [
    "javascript",
    "javascriptreact",
    "typescript",
    "typescriptreact"
  ],
  "prettier.requireConfig": true
}
Enter fullscreen mode Exit fullscreen mode

Step 8: Start the Applications

Run the start script from the root of the monorepo:

pnpm start
 // OR
npm run start
Enter fullscreen mode Exit fullscreen mode

SurveyJS custom survey software

JavaScript UI Libraries for Surveys and Forms

SurveyJS lets you build a JSON-based form management system that integrates with any backend, giving you full control over your data and no user limits. Includes support for custom question types, skip logic, integrated CCS editor, PDF export, real-time analytics & more.

Learn more

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more