T3: Rise of the Monorepo
Building full-stack monorepo's doesn't have to be a headache. With the T3 stack we can quickly spin up full-stack, typesafe Next.js projects.
What is the T3 stack?
create-t3-app
is a wonderfully opinionated CLI to create full-stack, typesafe Next.js projects quickly.
The T3 stack at its core is just a Next.js and Typescript CLI that works incredibly well out of the box. It does allow you to opt into nextAuth, Prisma, Tailwind, or tRPC.
NextAuth
NextAuth.js is an open-source project for adding authentication to your projects. Its provider list is extensive and works really well with Next.js. Combined with its Prisma adapter, we can easily create and manage authentication for our React application.
Prisma
Prisma is a Node.js and TypeScript ORM for managing databases that allow us to easily create database tables and data structures to manage data in our applications.
tRPC
tRPC, short for “Typescript Remote Procedure call” is a tool that allows us to create RPCs (much like a normal API endpoint) that support type inheritance to the frontend client that is consuming these endpoints. This means any changes to types on the server will be passed down to the client and give us type errors before anything is sent to production.
Tailwind CSS
Tailwind is a utility-first CSS framework that helps bridge the gap between opinionated frontend frameworks (MUI, Bootstrap, etc.) and the hard start of starting from scratch (Normalize, Reset). Do you want bold? <p className=”font-bold”>
Do you want rounded corners? <div className=”rounded”>
. It’s inline CSS, but easier to read, faster to write, and has tree shaking.
So, what makes Create T3 App worth your time?
Modularity
It’s super easy to plug in any package you want to use and get things working in the Next.js + Typescript environment. Maybe you really want to stick with GraphQL or use your preferred ORM, that’s no problem, just don’t install tRPC or Prisma during setup and you can configure your Next.js + TS stack to work to your liking. But, if you want to get going quickly, it works very efficiently out of the box and gives you the ability to quickly integrate any project-specific dependencies without the overhead of having to set up a specific stack before you can start building. Modularity also means it’s much easier to learn an individual package and implement it than having to commit to learning a monolithic framework and making sure it has the features you may or may not need in the future.
Flexibility
It gives you the agency to build and create things the way you want to. Sometimes you want to stick with what you know, and other times you want to try and implement something new, this stack lets you do both. T3 automatically configures your package manager based on how you create the app so npx create-t3-app@latest
uses npm, yarn create t3-app
uses yarn, pnpm dlx create-t3-app@latest
uses pnpm. Just as it should be 😉.
What are the T3 red flags?
There aren’t many T3 red flags, but consider if your project would have any issues with the following to see if they’re actually deal breakers. At the very least, come up with a plan on how you want to address them and know at what point they would become real pain points.
It's a Monorepo
tRPC doesn’t do well outside of a monorepo setup. Its strength comes from actively building and modifying types on the server side and then having TypeScript inference do its magic on the client side to avoid any typing issues.
Scalability
Prisma and tRPC both have the possibility of performance issues at scale. Prisma begins to have performance issues when you need to run substantial, heavy queries or if you have complicated nested queries. With tRPC, you’ll start to see the TypeScript server begin to slow down if you’re doing a couple hundred queries and/or mutations per second. With tRPC v10, they’ve improved performance to a few thousand per second, but with a library that relies so heavily on inference, you're still likely to see things slow down as your project continues to grow. Fortunately, because tRPC is built using normal functions, it’s super easy to migrate away from when the scale of your project demands it.
Theo, the author of T3, has a great video on why his stack “kinda sucks” that I’d definitely encourage you to check out if you’re looking for any weaknesses that might come back to haunt you.
What was my experience like?
There is nothing better than a slick CLI. Create T3 delivers on this. It’s super easy to set up, implement, and there doesn’t feel like any overhead to keep you from diving into building your project. It sets up your package manager based on your installation method and you hit the ground running.
The promise of modularity was definitely delivered on and continues to shine as one of the best parts of the T3 stack. This meant I could easily pick up any of its individual packages, take a crash course on them, and build out a feature-rich experience with them. It doesn’t dictate how you should build things, but rather gives you the building blocks to implement your application however you see fit. As far as other packages I may want to use, I have no doubt I could take them and integrate them into the foundations that the T3 stack provides.
The one piece that did feel missing was state management. It’s easy to over-optimize and overcomplicate things out of the gate, but if you know your project is going to have a level of complexity that would benefit from a state management tool, T3 doesn’t accommodate that out of the box. In my experience, having a tool like MobX to help manage state is an invaluable addition for more complex applications. I think it would be nice for T3 to take a stance on which state tool is best for the stack and provide some examples/configs for jump-starting a large project. They’re already doing this with an ORM in Prisma and for CSS in Tailwind, so there is precedent for this. Without state management, T3 relies heavily on React Context to manage shared data across the app (user session data for instance). tRPC wraps React Query to manage any of your route-specific data fetching needs. If the combination of these two meets your needs, then you’ll be set. Otherwise, if you need a more advanced state management tool, you’ll have to implement something on your own. Create T3 app recommends Zustand.
My takeaway
T3 makes me excited about full-stack apps again. As a front-end developer, it’s easy to get into these front-end/back-end silos and T3 helps break those down by implementing a monorepo approach that doesn’t feel hacky or compromised.
How I would start if I was you
T3 makes this particularly easy, but identify the pieces that you can break out and take crash courses on those individual parts. Start with as broad a crash course as you can. If you don’t know Next.js or Typescript I would start with these:
- Learn Next.js With TypeScript in 30 Minutes
- Next.js Crash Course
- Next.js in 100 Seconds
- Total TypeScript
- TypeScript Crash Course
If you’ve never used heard of NextAuth, I’d start here:
If you’ve never used heard of Prisma, I’d start here:
If you’ve never heard of tRPC, I’d start here:
If you’ve never heard of Tailwind, I’d start here:
Happy coding!