Sharing a full-stack project monorepo template with ts-rest + React + Fastify

Kevin Firko
Published:

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:

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 API
  • apps/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 + API
  • packages/contracts - ts-rest contract definitions implemented by UI + API
  • packages/data - shared types and zod schemas that define, parse, and validate data across the workspace
  • packages/react-ui - shared react component library with several components originating from shadcn/ui
  • packages/style - home to the cn() css utility and any tailwind-merge customizations
  • packages/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 with supertest 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’s workspace: 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 rules
  • prettier and editorconfig 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

Check it Out

https://github.com/firxworx/ts-rest-workspace