Introduction and goals
In this video I'm going to show you how you can create a monorepo with Turborepo. We'll be combining a Next.js project and a NestJS project into a single repository using Turborepo. Hi everyone, my name is Vahid and I'm your host on the Sakur channel. If you're interested in learning more about NestJS and Next.js be sure to subscribe to my channel for in-depth tutorials and courses. I'll also be covering more monorepo projects in the future, so let's get started.
Install Turborepo and create the monorepo
All right. In the first step we need to install the turbo package. So I want to install it with npm: npm i -g turbo, and then -D? Global because we need to install it globally, right? So let's install that. As you can see it is installed and now we can create a monorepo project with the turbo. So I'm going to say npx create-turbo@latest and it asks where we want to create our turbo repo. I'm going to say install it inside the count directory and then slash nest-next-turbo and then choose the package manager or choose npm. We need to wait until it downloads the packages. It will actually create two applications for us: apps.doc and apps.web. These two projects are actually Next.js projects, and there are packages that can be shared between the projects. Inside this repo we're going to create our Nest application. After installing and installing dependencies of this turbo repo, all right it's done and let's open the monorepo with VS Code.
Explore generated apps and node_modules layout
All right. So as you can see we have an apps directory here and inside it we have the doc which is a Next project. As you can see it uses the app directory and it has the latest version of Next. The other project is web that we can use for developing our front-end application. In our use case we don't need these docs here so we can just easily remove docs from our apps directory. If I take a look at our web project you can see there is not a node_modules inside it. The node_modules is in the root path of our turbo repo and it contains all the packages that are required by all the projects inside our monorepo.
Install NestJS CLI and create API app
So now let's install NestJS in our monorepo. I open up the terminal and go to the apps directory and inside it we can easily create a new Nest project. First we're going to install the Nest CLI: npm i -g @nestjs/cli because we want to install it globally. All right. Now we can create our NestJS application. As you can see we are inside the apps directory of our turbo repo, so here inside it we're going to say nest new and then put the name of our project. I'm going to go ahead with api and choose the package manager, go with npm. All right it's done and if I go to the apps directory now you can see we have an api project and it is the NestJS application. If I look at the node_modules here you can see it does not contain the packages for our NestJS application, but if I go to the node_modules in the root path of our turbo repo you can see it has the packages for our NestJS project. The @nestjs package is here inside the node_modules within the root path of our application.
Share packages from root and explain workspace behavior
So as I said, if we want to share a package between all projects inside our monorepo you can install it in the root path of our turbo repo and then use that package in both projects without installing that package in both projects. We just install it once and use it in both projects. So now let's close the node_modules here and here let's open the turbo.json. Let's close off the terminal. We have a dev object here, and if I open up the terminal again, get back to the root path of our monorepo and let's clear this first, and here let's run npm run dev. As you can see now the web project is running, but the NestJS application is not running. Actually this npm run dev will look for the package.json file in all of the projects that are inside the apps directory. For example it looks for the package.json file inside the Next.js application and it looks for the dev script here and runs this script for us. But if I go to the api directory which contains the NestJS application, open up the package.json, there you can see it doesn't contain the dev script inside the scripts section of the package.json, so Turborepo can't run this application with the dev command.
Add dev script and run both apps together
So if I change the start:dev here to just dev and restart our monorepo, so again let's run npm run dev. It runs both applications: api and the web. So we can navigate between these two consoles with arrow keys on the keyboard. This is the Next.js application that is running on port 3000 and this is the Nest application. We have an error here and that's because it tries to run the application on port 3000, but this port is already taken by the Next.js application. So if I go to the src directory of our NestJS application and open up the main.ts file and change the port to, for example, 8000 and save it, you can see now it runs the application without an error. And again with the arrow keys we can navigate between the consoles of our two projects. That's a great tool for creating monorepos.
Install and use shared Zod package
Now let's install Zod package in the root path of our application and use it in both projects. So let's stop the monorepo and here as you can see we are in the root path of our turbo repo. Let's install Zod package: npm i zod. All right. Now let's go to our Next.js application in the web directory and here inside the homepage let's use the Zod package. So for example let's say const schema = zod.object and then let's create a simple schema: for example name is going to be z.string. Right, it works without any error. So let's run the application again: npm run dev. The Next.js application is running without any error. And now let's use the Zod package inside our NestJS application. So I go to the apps directory and I go to app.service here and let's just create a z schema: const schema = z.object and let's create a simple schema for here again it is going to be z.string. All right. Now if I open up the terminal and navigate to the api project you can see our api application is running without any error, and if I go to the node_modules of the api application we can see that the Zod package is not there but instead it's on the node_modules of our turbo repo project. It's here inside the turbo repo's node_modules. So yeah, that's it for sharing a package between our projects.
Build both projects and final notes on workspaces
Now let's build our application. So let's stop the server and let's say npm run build. It looks for the build script inside the package.json file of all the projects inside the apps directory. If I run that you can see now our Next.js is in the building process, and in this way we can just build both projects with just one command with Turborepo. As a last thing let's take a look at the package.json file inside the turbo repo and as you can see we have a workspaces array here which actually specifies the workspaces in our application. Simply put, a workspace is a self-contained project inside our monorepo that can be independently developed. That's why we installed the NestJS application in the apps directory; it actually contains all projects inside our mono. That's it for this video. We have created a monorepo with two projects: Next.js and NestJS using Turborepo. If this video was helpful for you please hit the like button and if you haven't subscribed to the channel I have a lot of comprehensive courses and tutorials about Node.js frameworks mainly on Next.js and NestJS. You can consider subscribing to my channel to get informed about updates. Have a nice time and stay tuned for my next video. Bye-bye.