← Back to list

Setting up Turborepo with NextJS 12 and TailwindCSS 3, ESLint and Prettier.

The main driving force for this article is to hopefully help someone who finds them self in an oddly similar situation that I did, needing…

Ajay Titus · 2024-04-01 17:17 · 0 claps · 4.2 min read
#nextjs-12 #turborepo #tailwind-css #eslint #monorepo
Open on Medium ↗
Wiki topics: 🌐 · Web Development

Setting up Turborepo with NextJS 12 and TailwindCSS 3, ESLint and Prettier.

The main driving force for this article is to hopefully help someone who finds them self in an oddly similar situation that I did, needing a to migrate multiple NextJS 12 projects into a monorepo that shared a set of components. Or if you clicked on this guide through wayward curiosity, then rest assured your traffic will help getting this in front of those who need it. Skip to the end if you’ve got an issue transpiling packages and build errors.

Project Structure

If you’re not already familiar with what a monorepo is and what Turborepo does, I highly recommend reading up the official documentation or going through comparison articles.

One last thing before we jump in setting up Turborepo, the naming convention when it comes to monorepos can be slightly confusing depending on the source. To clear things up right out of the gate, here’s what I mean:

  • A Turborepo project: the single repository that houses code for multiple applications (called workspaces), their shared packages and overall configuration.
  • A Workspace: A subset of the turborepo that could be a frontend or backend application or even a folder with shared components or scripts. Each workspace has their own package.json that describes them and their dependencies.

Now enough stalling lets setup the Turborepo Project root.

The first couple of things you’ll need is:

  • apps folder — for each of your workspaces
  • packages folder — for shared code
  • package.json — to describe the monorepo overall
  • turbo.json — to define turborepo configuration

Leave the first two folders empty for now and move onto the package.json.

// package.json
{
    "name": "turborepo",
    "version": "0.1.0",
    "private": true,
    "packageManager": "npm@8.11.0",
    "scripts": {
        "dev": "turbo run dev --parallel",
        "dev:web": "turbo run dev --filter=web",
        "dev:docs": "turbo run dev --filter=docs",
        "build": "turbo run build --parallel",
        "build:web": "turbo run build --filter=web",
        "build:docs": "turbo run build --filter=docs",
        "start:web": "cd apps/web && npm run start",
        "start:docs": "cd apps/docs && npm run start"
    },
    "workspaces": [
        "apps/*",
        "packages/*"
    ],
    "devDependencies": {
        "prettier": "^3.2.5",
        "turbo": "^1.12.4",
        "@tailwindcss/line-clamp": "^0.3.1"
    }
}
  • Workspaces: The paths where your workspaces reside. Technically the shared packages are each their own workspace.
  • Scripts: Turborepo boasts the time it can save when building complicated interdependent systems, so with the — parallel flag you can spin up dev servers or build scripts of all the workspaces in the apps folder simultaneously. Or use the --filter flag to pick which workspaces you want to focus on. The turbo commands for dev and build run the respoective scritpts in the workspace package.json

Next, the turbo.json file, which lets you harness the functionalities of Turborepo. But to keep things simple, this is all you need to get started.

// turbo.json
{
    "$schema": "https://turbo.build/schema.json",
    "pipeline": {
        "build": {
            "outputs": [".next/**", "!.next/cache/**"]
    },
    "dev": {
        "cache": false
    }
}
  }

Shared Packages

Now let’s setup the shared configuration and components. You can create shared configuration and use them selectively, allowing certain workspaces to use their own unqiue config.

To make quick work of this section, here’s how your folder structure should look like:

- apps
- packages
  - config
    - .eslintrc.js
    - package.json
    - postcss.config.js
    - tailwind.config.js
package.json
turbo.json

This important file here is the package.json , which should have a unique name which you’ll reference later.

{
    "name": "config",
    "version": "1.0.0",
    "description": "shared configuration",
    "license": "MIT",
    "files": [
        ".eslintrc.js",
        "postcss.config.js",
        "tailwind.config.js"
    ]
}

The other files here follow their respective formats but they must be JS or TS files (rather than JSON) so that they can be imported into other workspaces.

You can create as many other shared packages as you want. One folder which holds all shared code or a bunch of distinct folders that distribute code among them. Here’s how a single shared components folder would look like.

- apps
- packages
  - config
  - shared
    - components
    - hooks
    - styles
    - utils
    index.js
    package.json
package.json
turbo.json

The only two important files here are index.js and package.json . The package.json file gives the package a unique name and specifies the main export file. The name here uses an @repo/ naming convention. This is optional and can be literally anything else, however it clues any developer that these components come from a significantly unique location.

// packages/shared/package.json
{
    "name": "@repo/shared",
    "version": "1.0.0",
    "license": "MIT",
    "main": "./index.js"
}

Then in the index.js you export any and all of the files under this package.

// index.js
export * from "./components/accordian";

export * from "./hooks/useWindowSize";

export * from "./utils/splitTextToArray";

Workspace

Lastly, we setup the workspaces of this Turborepo. Once again, create however many or few workspaces you need. For example, a Turborepo with two workspaces: web for a primary website and docs for a detailed documentation website. Each workspace is its own independent NextJS 12 project with all the configuration you would expect.

When you want to use any shared config, you create a corresponding file and import the config from the shared package.

// apps/web/.eslintrc.js
module.exports = require("config/.eslintrc.js")

Next, we import the shared components @repo/sharedin the workspace package.json

// apps/web/package.json
{
  "name": "web",
   "scripts": {
    "dev": "next dev",
    "build": "next buil",
    "start": "next start",
    "lint": "next lint",
  },
 "dependencies": {
    "@repo/shared": "*",
    "next": "12.1.0",
    "next-transpile-modules": "^9.1.0",
    "react": "17.0.2",
    "react-dom": "17.0.2"
  },
}

Then in any of your workspace components, you can import a shared file just like you would from a external package or library.

// apps/web/components/banner.jsx
import { useWindowSize } from "@repo/shared/hooks/useWindowSize";
// ...
const Banner = () => {
  const { size } = useWindowSize()
}

Last and most importantly, you will need to make one fix to allow this setup to work without crashing.

Transpiling Modules in NextJS 12

As mentioned earlier, your shared files are being imported similarly to external packages which you manage with a package manager. However, NextJS’ bundler will throw an error due to your shared code not being transpiled properly.

If your project is NextJS version 13 or over, just add this [transpilePackages](https://nextjs.org/docs/app/api-reference/next-config-js/transpilePackages) option and specify your shared packages.

However, if you’re on NextJS 12 and under, you will need this workaround.

  1. Install [next-transpile-modules](https://www.npmjs.com/package/next-transpile-modules)
  2. Configure your next.config.js for each workspace as such
const withTM = require('next-transpile-modules')(['@repo/shared'])
// List out all of your shared packages which import code in the array above

module.exports = withTM({
  async headers() {}
  // add the rest of your next config here
})

With that, you’re all done. Give yourself a clap on the back and run turbo build with your fingers crossed.


메타데이터
post_id
806e5aa5f454
slug
setting-up-turborepo-with-nextjs-12-and-tailwindcss-3-eslint-and-prettier-806e5aa5f454
url
https://medium.com/@ajaytitus1386/setting-up-turborepo-with-nextjs-12-and-tailwindcss-3-eslint-and-prettier-806e5aa5f454
canonical_url
https://medium.com/@ajaytitus1386/setting-up-turborepo-with-nextjs-12-and-tailwindcss-3-eslint-and-prettier-806e5aa5f454
author_url
https://medium.com/@ajaytitus1386
status
ok
fetched_at
2026-06-27 18:20:27