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
- Install the required prereqs
- requires node 18 (recomend using nvm)
- requires pnpm
node install -g pnpm
-
View env options
pnpm envSchema
-
Start the server
pnpm start
-
View the docs/playground at localhost:7300
-
Try making a change to the hello route at HelloRoute.ts
- typescript
- tRPC for typesafe routes
- tRPC-playground for automatic doc generation
- fastify for a peformant server
- fastify-metrics for automatic metrics
- prisma for typesafe database connections
- pnpm for fast node module installation
- nvm for consistent node versions locally and on CI
- zod for typesafety
- preconstruct for generating packages to be consumed in monorepo or on npm
- docker as an optional way to deploy app
- github actions for basic CI/CD
- prettier for code formatting
- eslint for linting
- babel for faster compiles than tsc
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 is the easiest way to build robust typesafe APIs for typescript clients. https://trpc.io
Trpc is wrapped internally at src/utils/Trpc.ts
The client above is not importing any code from the server, only its type declarations.
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
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
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 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 is an npm/yarn alternative that is much faster. https://pnpm.io/ .
The commands are for the most part the same as NPM.
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 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 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 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 are simple yml files that allow us to trigger workflows to run on certain github events. They are configured in .github folder
Prettier is a tool for formatting code with a consistent style. Prettier is configured in .prettierrc
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 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.
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
The architecture is very simple
- The Server class is the server and has an Api
- The Api class is the api and has routes
- The routes class are routes and they have TRPC route handlers
The src folder
has Api.ts, Server.ts, and the main index.ts folder. Utils live in utils
and routes live in routes
.
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.
The Server
class is the main entrypoint to the server. It starts a Fastify server and initializes it with a TRPC 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.
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
.
Process.env is wrapped with a class that peforms basic validation on it and documents what the env variables are src/Env.ts
.
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
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.
Basic github actions for running test, lint, and testing the build exist in .github/workflows
.
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