Sharing a full-stack project monorepo template with ts-rest + React + Fastify
This article introduces a new full-stack project template that I created to showcase ts-rest that includes an example blog app implemented with Fastify and React.
The repo is a pnpm workspace aka monorepo that’s 100% ESM with several internal packages that include common utilities, client/server contracts, zod schemas, a tailwindcss preset, and more.
The template is on GitHub: firxworx/ts-rest-workspace
The stack:
- React + Vite UI with react-router + react-query + tailwindcss + shadcn/ui
- Fastify API with pino for structured logging
ts-rest provides an efficient RPC/TRPC-like developer experience using JSON/REST for client/server communication instead of custom stack-specific protocols.
Flexing ts-rest
ts-rest is used to define type-safe contracts that are consumed and implemented by the API and UI to guarantee data integrity and type-safety.
Contracts
A ts-rest contract definition specifies endpoints, associated HTTP methods, and zod schemas that describe request and response bodies, query parameters, headers, and optional metadata.
Contracts for posts (blog posts) and hello (a simple example) are defined in the @workspace/contracts
package.
I included two contracts to demonstrate how to combine multiple contracts as this is a likely requirement of any real-world project.
React UI
The React app uses ts-rest’s RPC-like client to communicate with the back-end JSON/REST API. The client provides fully-typed parameters and request/reponse bodies based on the project’s contracts.
The project template uses the client powered by react-query to take advantage of the library’s powerful capabilities with caching and error handling.
ts-rest offers several client options: react-query, fetch API, and vue query, and it supports custom clients. The docs provide an example of a custom client with axios.
Fastify API
The Fastify API imports ts-rest’s contract router to implement its contract responsibilities.
Requests and optionally responses are automatically validated and ts-rest delivers strong typing based on the contracts.
Project Layout
Apps
apps/ui
- React + Vite SPA using ts-rest’s react-query client to call the APIapps/fastify-api
- Fastify API server using ts-rest to implement the back-end of the contract
Packages
packages/common
- shared code and utilities for use by both UI + APIpackages/contracts
- ts-rest contract definitions implemented by UI + APIpackages/data
- shared types and zod schemas that define, parse, and validate data across the workspacepackages/react-ui
- shared react component library with several components originating from shadcn/uipackages/style
- home to thecn()
css utility and anytailwind-merge
customizationspackages/tailwind
- shared tailwindcss preset providing a common tailwindcss config
Assorted Features
API
- 100% ESM and built/bundled using
esbuild
to a form suitable for both containerized and serverless deployments - The dev server runs with
tsx watch
to enable fast iteration - The Fastify API includes
vitest
configured withsupertest
for testing API routes
Dependencies
syncpack
to keep the versions of dependencies amongst different apps and packages in the workspace in sync- customized
syncpack
configuration that supports pnpm’sworkspace:
protocol for internal package dependencies
Docs
- comprehensive documentation and comments that don’t assume you already know everything about this complex ecosystem
- each app and package has its own
README.md
with additional information and setup instructions
Linting
eslint
with the new v9+ flat config syntax with compatibility for legacy plugins and rulesprettier
andeditorconfig
configuration files- shared workspace eslint/prettier configuration for performance and to avoid OOM issues
QA
- There’s a
vitest
configuration in all packages including with@testing-library/react
for React components - Example tests are sprinkled throughout with representative examples
VSCode
.vscode/settings.json
is included for VSCode users with recommended settings for the workspace to support eslint v9 and improve performance