/server-boilerplate

A simple server boilerplate based on Fastify, TRPC, and Prisma

Primary LanguageTypeScriptMIT LicenseMIT

Twitter

Server Boilerplate

Simple opinionated boilerplate for scaffolding scalable production ready servers.

This boilerplate optimizes for typesafety while building internal APIs consumed by typescript.

Note: This boilerplate can work as an external facing API if using Open API as described later in README

Getting started

  1. Install the required prereqs
  • requires node 18 (recomend using nvm)
  • requires pnpm node install -g pnpm
  1. View env options pnpm envSchema

  2. Start the server pnpm start

  3. View the docs/playground at localhost:7300

  4. Try making a change to the hello route at HelloRoute.ts

Technologies

Typescript

Typescript allows javascript code to be statically analyzed based on it's types.

This boilerplate heavily optimizes for typesafety with other tools such as Zod, TRPC, and Prisma.

Note we do not compile our code with typescript as typechecking can be slow as projects grow and instead do typechecking seperately as a lint step with yarn typecheck while using babel to compile the code faster

Typescript is configured in tsconfig

The current typescript config is the most strict typescript config possible. Even stricter than strict mode. Typescript specific eslint rules are also included.

TRPC

TRPC is the easiest way to build robust typesafe APIs for typescript clients. https://trpc.io

Trpc is wrapped internally at src/utils/Trpc.ts

Demo

The client above is not importing any code from the server, only its type declarations.

tRPC playground

Docs for all trpc routes along with a playground are automatically served at /playground. https://github.com/sachinraja/trpc-playground

Trpc playground is configured by the server in src/Server.ts

image

Fastify

Fastify is a highly peformant server that replaces express. With minor modifications this server will work with express, aws lambdas, next.js or any other way of using the trpc server that trpc supports. https://www.fastify.io/.

Fastify is wrapped at `src/utils/Fastify.ts

Fastify Metrics

Metrics for all routes are automatically served at /metrics. https://github.com/SkeLLLa/fastify-metrics

Metrics are configured by server in src/Server.ts

Prisma

Prisma is a typesafe way of interacting with a db. https://www.prisma.io/.

To start using prisma simply run the prisma cli command to get started. Prisma will automatically generate a prisma client that you can use in your routes

npx prisma

Pnpm

PNPM is an npm/yarn alternative that is much faster. https://pnpm.io/ .

The commands are for the most part the same as NPM.

Nvm

Nvm is a way to guarantee everything is using the same version of node. This is useful for eliminating an entire class of bugs. Engines in package.json will warn if node version does not match. Install nvm and run nvm use to automatically be on correct version.

Zod

Zod is an amazing tool to validate unvalidated input into typesafe values. https://github.com/colinhacks/zod.

It is used to validate routes and create automatic typesafe clients for any typescript clients using the service.

Preconstruct

Preconstruct is a very simple but robust nearly 0 config tool to build typescript packages for npm distribution. All the config lives in package.json.

Preconstruct will generate types, commonjs javascript, and esm modules along with .d.ts type files ready to be distributed by npm or consumed by other packages in a monorepo https://preconstruct.tools/guides/building-typescript-packages

Docker

Docker is a popular tool for deploying predictable builds including the system it's running on. A docker image is supported to be ran just about everywhere

A Dockerfile is included along with a Workflow for automatically publishing to dockerhub.

Github actions

Github actions are simple yml files that allow us to trigger workflows to run on certain github events. They are configured in .github folder

Prettier

Prettier is a tool for formatting code with a consistent style. Prettier is configured in .prettierrc

eslint

Eslint is a tool for linting JavaScript code. Eslint is configured in .eslintrc.js

The included eslint config prefers rules with autofixers and rules that can catch actual bugs (such as no floating promise)

babel

Babel is a very simple tool for transpiling JavaScript Babel is configured in babel.config.js Babel just removes the typescript types. It does not typecheck. It is recommended to use babel for any other tools that need to transpile typescript, for example jest, as babel will be much faster than the typescript compiler.

Development

Print env options

pnpm envSchema

Run server in watch mode

pnpm start

Build and start server

pnpm build && pnpm serve

Lint with prettier and eslint

pnpm lint

Explore prisma cli

npx prisma

Architecture

The architecture is very simple

  1. The Server class is the server and has an Api
  2. The Api class is the api and has routes
  3. The routes class are routes and they have TRPC route handlers

Folder structure

The src folder has Api.ts, Server.ts, and the main index.ts folder. Utils live in utils and routes live in routes.

Dependency Injection

This boilerplate makes heavy use of dependency injection to make testing easier and dependencies explicit, and the server more modular and a simple architecture that scales to being usable by larger teams.

Server

The Server class is the main entrypoint to the server. It starts a Fastify server and initializes it with a TRPC api.

API

The Api class is where new routes are registered. THe API itself is a route that handles /api/ and it's routes can optionally have nested routes.

Routes

For most tasks, you will only need to create or touch routes. All routes are in the src/routes folder.

Routes are set up to be scalable to larger teams and support nested apis/routes.

For an example of defining a route checkout src/routes/hello.ts. The route is registered on the api at src/Api.ts.

Env

Process.env is wrapped with a class that peforms basic validation on it and documents what the env variables are src/Env.ts.

CI/CD

A basic CI/CD setup exists with github actions.

To setup you must set up some secrets in your repo and configure branch protection rules

Deployments

A basic dockerfile is provided for convenience. This boilerplate can easily be modified to work with most serverless deployments as well as next.js.

Github actions exist for both publishing package to npm and publishing docker image to dockerhub.

CI

Basic github actions for running test, lint, and testing the build exist in .github/workflows.

OpenAPI

This boilerplate is optimized for building internal APIs as parts of larger systems. The api is optimized for consuption by typescript clients. For external facing apis that are potentially not consumed by typescript clients, I'd recomend adding OpenAPI to the trpc setup. I didn't add it here because OpenAPI does require the extra boilerplate of specifying .output zod validators as well as a meta tag in every route. But it's a great option to turn some of the internal apis to external apis and may be added to this boilerplate in the future

Author: Will Cory 👨🏻‍💻