A modern turborepo template for building fullstack projects with modular components, shared configs, containerised deployments and 100% type-safety.
This project is heavily inspired by RT Stack and shares many of its principles and architecture. However, it includes some modifications and enhancements tailored to my preferences and use cases.
Below is an overview of all the components in the stack:
apps
├─ web
| ├─ react (vite)
| ├─ tanstack (router, query, form)
| └─ tailwindcss
├─ server
| └─ hono (wrapper for api & auth)
packages
├─ api
| └─ trpc with zod
├─ auth
| └─ better auth
├─ db
| └─ drizzle orm (postgresql database)
├─ email
| └─ resend client to send email + react-email
├─ intl
| └─ internationalization with i18n + i18next
├─ ui
| ├─ tailwindcss
| └─ shadcn & radix ui
tools
├─ eslint
├─ prettier
├─ tailwind
└─ typescript
View all catalog dependencies in pnpm-workspace.yaml.
The following features are implemented out-of-the-box:
- login/register/reset-password/organizations/ (using better-auth email/password) credentials provider
- themes (dark/light mode using next-themes)
- web/server integration (trpc API example for creating/listing posts)
Many aspects of the RT Stack were derived from the t3-oss/create-t3-turbo. However, there is a preference for:
- tanstack router (web) + hono (server) instead of nextjs (fullstack)
- better auth for authentication instead auth.js (next auth)
- zod for input validation
- tanstack form instead of react-hook-form
- using
.env
in each application/package instead of globally, as per turborepo's recommendations
Additionally, the aim of this project is to always adopting the latest releases of dependencies and tools. For example:
- react v19
- tailwindcss v4 & shadcn-ui (canary)
- trpc v11
- eslint v9
- pnpm v10
Ensure the following tools are available on your system:
- node (version 22+)
- pnpm (version 10+)
- postgres database, which you can easily run using tools like:
- docker and docker-compose
- podman and podman-compose
- supabase's free tier cloud database
# Create a repository using the rt-stack template (replace YOUR_PROJECT)
pnpm dlx create-turbo@latest -m pnpm -e https://github.com/nktnet1/rt-stack YOUR_PROJECT
# Enter the directory or open in your IDE (replace YOUR_PROJECT)
cd YOUR_PROJECT
# Install all dependencies for apps and packages
pnpm install
# Set up environment variables in packages/db (for migration) and apps/*
pnpm copy-example-env
# Start a local postgres instance in the background (e.g. using docker)
docker compose up db --detach
# Generate drizzle schema to your database
pnpm db:generate
# Push drizzle schema to your database
pnpm db:push
If you use an external postgres database, you will need to modify the following environment variables:
-
SERVER_POSTGRES_URL
in the fileapps/server/.env
- used at runtime by the backend server
-
DB_POSTGRES_URL
in the filepackages/db/.env
- used in database schema migrations with
pnpm db:push
- used in database schema migrations with
You can then start all applications with
pnpm dev
By default the following URLs will be accesibile:
- web application: http://localhost:8085
- backend server: http://localhost:3035
Use pnpm --filter=<name>
(where <name>
is defined in the package.json
of each package).
Example usage:
# Install the nuqs package for our web application:
pnpm --filter=web install nuqs
# Format only the ui package:
pnpm --filter=@repo/ui format
You can get a list of all package names using the command below:
find . -maxdepth 3 -name "package.json" -exec grep '"name":' {} \;
To install a single Shadcn/UI component, e.g. button
, use the command
pnpm ui-add button
You can also open an interactive cli shadcn/ui
pnpm ui-add
- press
i
to enter interactive mode on startup - use
j/k
(or arrow keys) to navigate up and down. - use
<Space>
to toggle select your desired component(s) - hit
<Enter>
to install all selected components
All scripts are defined in package.json and turbo.json:
pnpm typecheck # repot typescript isses
pnpm format # report prettier issues
pnpm format:fix # auto-fix prettier issues
pnpm lint # report eslint issues
pnpm lint:fix # auto-fix eslint issues
pnpm clean # remove all .cache, .turbo, dist, node_modules
pnpx codemod pnpm/catalog # migrate dependencies to pnpm-workspace.yaml
Both the web
and server
applications have been containerised. You can start
see this in action by running the commands:
# Start all applications
docker-compose up
# Push drizzle schema to your database - while you can use `pnpm db:push` on
# the host machine if you have installed all the required dependencies, it is
# also possible to do everything within docker.
# Open a second terminal and run the command:
docker compose run --rm drizzle
# Upon completion, you will be inside the `drizzle` docker container instead
# of the host machine. It is now possible to push the schema with:
pnpm db:push
You can then open the web link below in your browser:
Please note that these containers are run in production mode. For further details, see
The following is configured in vite.config.ts web application:
TanStackRouterVite({
routeToken: 'layout',
}),
This is to allow for a layout.tsx
file in each directory similar to NextJS.
You can read more about this
here.
There is an artificial delay added in development mode to simulate API usage in
real-world environments. You can disable this by removing the timingMiddleware
in ./packages/api/src/server/trpc.ts