Skip to content
Draft
19 changes: 16 additions & 3 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,8 +1,21 @@
# Description: Example of .env file
# Example .env file for local development and tests

# MongoDB URI
# MongoDB (optional)
MONGO_URI=mongodb://localhost:27017/your-database-name

# Auth Plugin
# OpenID Connect (used by the auth plugin)
# AUTH_DISCOVERY_URL should point to the provider's discovery document (/.well-known/openid-configuration)
AUTH_DISCOVERY_URL=https://login.microsoftonline.com/c917f3e2-9322-4926-9bb3-daca730413ca/v2.0/.well-known/openid-configuration
AUTH_CLIENT_ID=b4bc4b9a-7162-44c5-bb50-fe935dce1f5a

# When true, the auth plugin skips remote discovery and verification (useful for local testing)
AUTH_SKIP=true

# Optional runtime controls
NODE_ENV=development
PORT=3000

# Test helpers (optional)
# Provide these only when running integration tests that require a real token/user.
TEST_AUTH_TOKEN=
TEST_AUTH_USER=
32 changes: 12 additions & 20 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
# How to Contribute

Thanks for reading this, because we really need everyone to follow some collaboration guidelines to make our codebase
maintainable, clean and concise.
Thanks for taking a moment to read this. Following these collaboration guidelines helps keep the codebase maintainable,
clean, and easy to review.

The standard workflow to contribute to the project is as follows:

1. Create an issue to track the things (feature, bug or something else) you are working on. This also allows other
contributors to know what you are working on, and to potentially offer suggestions or help.
2. On the right hand side of the issue page, there is a button that allows you to create a new branch for the issue.
This will automatically create a new branch with the issue number and title. I strongly recommend you to use this
feature instead of creating a branch manually, because it will make it easier to track the issue that you are working
on.
2. On the right hand side of an issue page there is a button to create a branch for that issue. It will create a branch
named from the issue number and title. We recommend using that feature (rather than creating branches manually) to
make it easier to track work against the originating issue.
3. Make your changes in the new branch. Ideally, your commit messages should follow
the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) specification. We will rebase your PR
later if your commits are well-organized and the messages are well-formatted. Otherwise, we may ask you to fix them,
Expand All @@ -34,8 +33,8 @@ but we will try our best to achieve the following goals:
- Use iterative methods on collections instead of loops whenever possible.
- Avoid side effects in a function as much as possible.

That's not only because functional programming is cool, but also because it reduces the complexity of the code, and
makes it easier to reason about the code. For example, you should _never_ do:
Apart from functional programming being cool, this reduces complexity and
makes code easier to reason about. For example, you should _avoid_:

```typescript
const numbers = [1, 2, 3]
Expand Down Expand Up @@ -64,16 +63,12 @@ During the PR review process, we make use of GitHub comments to track suggestion
The general principles are the following:

- If the comment is a change suggestion...

- If it's clear and uncontroversial how to apply the suggestion, you should resolve the comment after you have made
- If it's clear and uncontroversial how to apply the suggestion, you should resolve the comment after you have made
the corresponding changes to the PR.

- If you are not 100% sure that you have applied the suggestion correctly, leave a comment asking it. Do not resolve
- If you are not 100% sure that you have applied the suggestion correctly, leave a comment asking it. Do not resolve
the comment in this case.

- If you don't fully understand or agree with the suggestion, reply to the comment with your questions and
- If you don't fully understand or agree with the suggestion, reply to the comment with your questions and
rebuttals. Do not resolve the comment in this case.

- If the comment is a clarification request, answer it. Do not resolve the comment in this case. We will either come
back with further questions or suggestions, or close the comment ourselves if we find your answer satisfactory.

Expand All @@ -86,8 +81,5 @@ Please make sure your code passes all automated CI tests (unless under special c
You may trigger them by simply pushing your commits to a branch, or by opening a PR. Reviewing a PR that doesn't pass
tests is a waste of time for everyone involved.

During code review, it is not supposed to happen that we have to keep coming back to your PR, continually finding more
problems more unpolished changes, and having to go through lots of back-and-forth interactions this way. This will only
lead to growing frustration on both ends.


During code review, please try to address issues thoroughly before requesting another round of review. This reduces
unnecessary back-and-forth and speeds up the process for everyone.
63 changes: 31 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,52 +1,51 @@
# USThing Template API

The template repository for USThing backend services, powered by Fastify.
A concise Fastify + TypeScript starter used by USThing backend services. This repository provides a minimal, well-tested scaffold with recommended scripts, linting, and CI configuration.

## Available Scripts
## Quickstart & developer setup

In the project directory, you can run:
See the detailed guides in `docs/`:

### `yarn run dev`
- `docs/quickstart.md` — quick start commands and example requests
- `docs/dev-setup.md` — Corepack, Node setup, and developer tips

To start the app in dev mode.
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
Note: this repository expects Yarn managed via Corepack. If Corepack is not enabled on your machine, enable it with `corepack enable`.

### `yarn run start`
## Key scripts

For production mode
- `dev` — start in development (watch + fastify)
- `build` — compile TypeScript
- `start` — run production server (from `dist`)
- `test` — build and run tests
- `lint`, `lint:fix` — ESLint checks and fixes
- `commitlint` — validate commit messages

### `yarn run test`
## Project layout

Run the test cases.
- `src/` — application code (routes, plugins, utils)
- `src/app.ts` — Fastify app and plugin registration
- `routes/` — route modules
- `test/` — tests and helpers
- `docs/` — human-authored docs (Quickstart, guides, migration)
- `.env.example` — example env variables

### `yarn run lint`
## Docs and API reference

Run the linter.
Human-facing guides belong in `docs/`. API specs (generated from code via Fastify+Swagger or TypeDoc) should be produced by CI and published to your docs site rather than frequently committing generated files.

Note that the format of the code will also be checked.
## Environment

### `yarn run lint:fix`
See `.env.example` for application-level variables. Fastify CLI options are documented at the `fastify-cli` project.

Run the linter and fix the issues.
## Contributing

Note that the format of the code will also be checked and fixed.
Please follow `CONTRIBUTING.md`. Use the configured commitlint rules and run lint/tests before opening a PR.

## Environment Variables
## Support

For Fastify-level environment variables, please refer to the [fastify-cli documentation](https://github.com/fastify/fastify-cli).
Open an issue on GitHub using the provided templates for bugs or feature requests.

For the application-level environment variables, please refer to the `.env.example` file.
## Learn more

## CI / CD

This template supports GitHub Actions for CI / CD. The available workflows are:

- Checks / eslint: Run ES Lint to check problems and the format of the code.
- Checks / commitlint: Run Commitlint to check the format of the commit messages.
- Checks / tests: Run unit tests of the project.
- Docker CI / docker: Build the Docker image and push it to the GitHub Container Registry.
- Release Please / release-please: Automatic releasing. See also [release-please](https://github.com/googleapis/release-please).

## Learn More

To learn Fastify, check out the [Fastify documentation](https://fastify.dev/docs/latest/).
- Fastify: <https://www.fastify.dev/>
- Docs folder: `docs/` (detailed guides and examples)
11 changes: 11 additions & 0 deletions docs/ci.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# CI workflows (overview)

The repository uses GitHub Actions. The active workflows are in `.github/workflows/` — check those files for exact steps. High-level:

- `check.yml` — runs lint, commitlint, and the test suite on pushes and PRs.
- `docker.yml` — builds and pushes container images for PRs and pushes.
- `release.yml` — run by `release-please` on `main` to automate releases and production image publishing.

When a check fails, open the corresponding workflow run in GitHub (Actions tab) to see job logs.

Avoid committing generated artifacts — have CI produce and publish them instead.
70 changes: 70 additions & 0 deletions docs/dev-setup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Developer setup

This file documents the minimal developer setup for the template-api project.

## Prerequisites

- Node.js >= 24 (LTS or newer recommended)
- Corepack (bundled with modern Node.js releases)

<!-- Node version management was moved to an optional section at the end of this document -->

## Enable Corepack

Enable corepack if not already enabled:

```bash
# enables Corepack globally
corepack enable
```

## Verify setup

Verify Yarn is available and the expected version

```bash
# Yarn should be available after enabling Corepack
yarn -v
```

## Installation

Install dependencies and prepare hooks

```bash
# install dependencies
yarn install

# prepare Husky git hooks (if present)
yarn run prepare
```

## Notes

- After enabling Corepack you can use `yarn` directly — there is no need to prefix commands with `corepack`.
- If the repository sets a Yarn version via `.yarnrc.yml`/`yarn.lock`, Corepack will select the correct Yarn release automatically.
- Keep your Node toolchain up-to-date for security and compatibility.

## Troubleshooting

- If `yarn` is not found after enabling Corepack, restart your shell or open a new terminal.
- If you need a specific Yarn release, run `corepack prepare yarn@<version> --activate`.

## Further reading

- Corepack: <https://nodejs.org/api/corepack.html>
- Yarn (Berry) docs: <https://yarnpkg.com/>

## Optional: Node version management

If you choose to use a Node version manager, pin a version in the repo (for example add a `.nvmrc` with `24`) so contributors and CI pick the same Node. Minimal examples:

```bash
# nvm
nvm install 24 && nvm use 24

# fnm
fnm install 24 && fnm use 24
```

This is optional but recommended for reproducible local builds and CI.
54 changes: 54 additions & 0 deletions docs/docker-and-deployment.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Docker & Deployment

This guide explains how to build and run the project's Docker image and where CI builds/publishes images.

## Provided Dockerfile

A `Dockerfile` exists at the repository root. It is used by the CI workflow `.github/workflows/docker.yml` to build multi-tag images and push them to the configured registry (default: `ghcr.io`).

## Local build & run

Build the image locally (from repo root):

```bash
# build
docker build -t template-api:local .

# run (expose port 3000)
docker run --rm -p 3000:3000 --env-file .env.example template-api:local
```

Replace `--env-file .env.example` with your `.env` file or explicit `-e` flags for required environment variables.

## CI image publishing

The repository's `docker.yml` workflow builds and pushes images to the registry. The workflow:

- sets up QEMU and Buildx
- logs into the registry using the workflow token
- generates metadata tags (sha, branch/ref, test)
- builds and pushes the image(s)

If you need to change the target registry or image name, update the `REGISTRY` and `IMAGE_NAME` environment variables in the workflow.

## Deployment notes

- Use environment variables (do not bake secrets into images).
- Prefer a runtime secret manager (Kubernetes Secrets, cloud secret manager) rather than `.env` in production.
- For Kubernetes, build image tags in CI (sha or semver) and deploy via your CD system pointing to those tags.

## Debugging

- To inspect a container locally:

```bash
docker logs <container>
docker exec -it <container> /bin/sh
```

- If the app fails to start in the container, check the `NODE_ENV` and required env variables, and run the same start command from within the container to reproduce.

## Further reading

- Docker Docs: <https://docs.docker.com/>
- GitHub Actions docker/build-push-action: <https://github.com/docker/build-push-action>
30 changes: 30 additions & 0 deletions docs/env-vars.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Environment variables

This project reads configuration from environment variables. A plain-text example file is provided at `.env.example` (copy it to `.env` for local development).

Recommended variables:

- MONGO_URI: MongoDB connection string (optional).
- AUTH_DISCOVERY_URL: OpenID Connect discovery URL (used by the auth plugin).
- AUTH_CLIENT_ID: OpenID Connect client id.
- AUTH_SKIP: When `true`, the auth plugin will skip external verification (useful for local tests).
- NODE_ENV: `development` / `production`.
- PORT: Port the Fastify server listens on (default 3000).

Test helpers (optional):

- TEST_AUTH_TOKEN: Bearer token used by integration tests (set only in CI or local secure env).
- TEST_AUTH_USER: Expected username for the test token.

How to use

Copy the example to a working `.env` file and modify values as needed:

```bash
cp .env.example .env
```

Notes

- Never commit real secrets. Use your cloud provider's secret manager or CI secrets for production deployments.
- Git: the repository ignores any file starting with `.env` (for example `.env`, `.env.local`, `.env.development`) — only the `.env.example` file is tracked. This keeps local or sensitive environment files out of version control while providing an example to copy from.
41 changes: 41 additions & 0 deletions docs/plugins.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Plugins

This file summarizes the plugins provided in the template and how they are loaded.

## Loading

- Plugins live under `src/plugins/` and are autoloaded by `@fastify/autoload` in `src/app.ts`.
- Plugins run before routes are registered so they can provide decorators, hooks, and shared schemas used by routes.

## About plugins

Plugins define cross-cutting behavior for your application (auth, DB, caching, helpers). Files in `src/plugins/` typically use `fastify-plugin` so they can expose decorators and hooks to the outer scope.

See also:

- The hitchhiker's guide to plugins: <https://fastify.dev/docs/latest/Guides/Plugins-Guide/>
- Fastify decorators: <https://fastify.dev/docs/latest/Reference/Decorators/>
- Fastify lifecycle: <https://fastify.dev/docs/latest/Reference/Lifecycle/>

## Key plugins

- `sensible.ts`
- Registers `@fastify/sensible` and exposes a shared schema id `HttpError` used in route schemas.
- Provides convenience reply helpers such as `reply.badRequest()`.

- `auth.ts`
- Adds authentication support via OpenID Connect discovery and JWT verification.
- Exposes a decorator `fastify.authPlugin(request, reply)` to validate requests; also sets `request.user` after successful auth.
- Options: `authDiscoveryURL`, `authClientID`, and optional `authSkip` to disable in local/testing.

- `init-mongo.ts` (optional)
- Placeholder plugin for MongoDB initialization (indexes, migrations). The actual MongoDB registration is commented out in `src/app.ts` and is optional.

- `support.ts`
- Example plugin demonstrating `fastify.decorate()` (adds `someSupport()` decorator returning a string).

## Extending plugins

- Add a new plugin under `src/plugins/` and export it as a Fastify plugin (use `fastify-plugin` to expose decorators).
- Keep plugin responsibilities narrow and reusable (auth, DB setup, metrics, tracing, etc.).
- Document plugin options and side effects inline in the plugin and in `docs/plugins.md` when needed.
Loading