Stop 10 · Full-Stack FrameworksTopics · 6/7

T3 Stack (Overview)

Part of the Full Stack Developer Roadmap

In short

The T3 Stack isn't a new framework. It's a hand-picked team, Next.js, TypeScript, tRPC, Prisma and Tailwind, set up so a typo in your API breaks the build instead of production.

An opinionated, popular starter combining Next.js, TypeScript, tRPC, Prisma, and Tailwind — a curated 'best practices' full-stack setup rather than a single new framework.

The blob character unpacks a cricket kit bag with bat, ball, helmet, pads and gloves laid out on grass.

Think of it like this

A balanced playing XI

Selectors don't pick eleven openers. They pick batters, bowlers, a keeper and an all-rounder who play well together. T3 is a selected XI for full stack TypeScript. And like a captain, you can drop a player at setup: skip auth or Tailwind if you don't need them.

Watch it happen

One typed call, page to database

React page
tRPC router
Prisma
Postgres

post.create({ title })

1/6The component calls a mutation. TypeScript already knows the input shape from the server code.

The big ideas

What you need to know

tRPC: no REST layer

You call server procedures like functions. Types flow from server to client with no code generation or OpenAPI file.

Prisma or Drizzle

A typed ORM turns your schema into a client with autocomplete, so queries are checked by TypeScript too.

Auth.js for login

NextAuth.js, now called Auth.js, handles sign-in with providers like GitHub or Google and gives tRPC a session.

Pick what you need

create-t3-app asks which pieces to include. It's a starting point, not a rulebook.

See it in code

Walk through the code

ts
1// src/server/api/routers/post.ts2import { z } from "zod";3import { createTRPCRouter, protectedProcedure } from "~/server/api/trpc";4 5export const postRouter = createTRPCRouter({6  create: protectedProcedure7    .input(z.object({ title: z.string().min(1).max(120) }))8    .mutation(({ ctx, input }) =>9      ctx.db.post.create({ data: { title: input.title, createdById: ctx.session.user.id } }),10    ),11});12 13// In a client component:14// const create = api.post.create.useMutation();15// create.mutate({ title: "Hello" });  // { title: 42 } would be a type error

1/4protectedProcedure rejects the call unless someone is signed in.

This follows the layout create-t3-app generates. ctx carries the database client and the signed-in user's session.

Save yourself the pain

Common mistakes

Oops

Using tRPC when a mobile app or another team's service needs your API.

Do this instead

tRPC shines when one TypeScript codebase owns both ends. For outside clients, expose REST or GraphQL as well.

Oops

Picking T3 for your very first project and getting lost in five new tools.

Do this instead

Learn Next.js and an ORM first. Then T3 feels like a time saver, not a puzzle.

Your mission

Feel the type safety

~40 min

Quick check

What does tRPC give a T3 app that a plain fetch to a REST route doesn't?

Go deeper

  1. 1Scaffold a project with `create-t3-app` and explore what it wires together.
  2. 2Notice how it solves the 'shared types between frontend and backend' problem via tRPC.
  3. 3Use it as a reference for how experienced teams structure a modern full-stack TypeScript app.

More topics at this stop

Stuck on this topic? Ask an Insider

Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.

Download
InsideEdge