npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@gjuchault/typescript-service-starter

v7.3.0

Published

Yet another typescript service starter template

Readme

TypeScript Service Starter

NPM NPM GitHub Workflow Status

Yet another (opinionated) TypeScript service starter template.

Opinions and limitations

  1. Follows Domain Driven Development and 3 Layers architecture
  2. As little of externalities requirements as possible (outputs to stdout/stderr, no auth management, optional cache, etc.)
  3. No dependency on node_modules folder and filesystem at runtime, to allow bundling & small Docker image
  4. Config should not default to either development or production (link)

And extends the ones from typescript-library-starter

  1. Relies as much as possible on each included library's defaults
  2. Only relies on GitHub Actions
  3. Does not include documentation generation
  4. Always sets NODE_ENV to production and use ENV_NAME for logging purposes

Getting started

  1. npx degit gjuchault/typescript-service-starter my-project or click on the Use this template button on GitHub!
  2. cd my-project
  3. npm install
  4. git init (if you used degit)
  5. node --run setup
  6. echo "HTTP_COOKIE_SIGNING_SECRET=$(node --run generate-secret)" > .env.local

To enable deployment, you will need to:

  1. Set up the NPM_TOKEN secret in GitHub Actions (Settings > Secrets > Actions)
  2. Give GITHUB_TOKEN write permissions for GitHub releases (Settings > Actions > General > Workflow permissions)

Features

HTTP Server and typed client

This template is based on Fastify with some nice defaults (circuit breaker, valkey rate limit, etc.). openapi-typescript is used to have nice routes & automatic client generation with zod and TypeScript.

Client should be published when this package is released. You can use openapi-fetch easily with it:

import createClient from "openapi-fetch";
import type { paths as api } from "typescript-service-starter";

export const client = createClient<api>({ baseUrl: "" });

const res = await client.GET("/api/docs");

You can check openapi-ts's documentation for more details.

Commands:

  • generate-client: creates the client/ folder with YAML and JSON OpenAPI schemas as well as openapi-typescript' schemas

Databases

It leverages PostgreSQL as a storage (through slonik), umzug for migrations, Valkey (or compatible like KeyDB or Dragonfly) as a cache through valkey.

Commands:

  • migrate:up: run migrations up to the latest one
  • migrate:down [n=1]: revert n migrations
  • migrate:create: create a new migration file

Telemetry

For the logging & telemetry part, it uses pino and OpenTelemetry (for both tracing and metrics). To handle distributed tracing, it expects W3C's traceparent header to carry trace id & parent span id (example header: traceparent: '00-82d7adc64d7020e7fe7ff263dd5ba4dc-dd932b8fbc70946d-01').

You can find an example of a working fullstack telemetry in docker-compose.yaml, where this service directly pushes to prometheus and jaeger without the use of a collector.

Layers & folder structure

src/
├── contexts       # contexts your service is handling (in the DDD sense)
│   ├── your-context
│   │   ├── application  # service code
│   │   ├── domain       # pure functions & TypeScript models of your entities
│   │   ├── presentation # communication layer (http)
│   │   ├── repository   # storage of your entities
├── helpers        # utilities functions & non-domain code
├── infrastructure # technical components (cache, database connection, etc.)
└── test-helpers   # test utilities (starting default port, resetting database, etc.)

Dependencies are passed as last-parameter so methods are testable easily and avoid mocking modules.

Node.js, npm version

TypeScript Service Starter relies on Volta to ensure Node.js version to be consistent across developers. It's also used in the GitHub workflow file.

TypeScript

Leverages node's type to avoid build step, but keeps tsc to generate .d.ts files.

Commands:

  • start: starts the bundled (see below) server with .env and .env.local env files
  • dev: starts src server with .env and .env.local files
  • worker: starts the worker with .env, .env.local env files
  • type:check: validates types with tsc

Production build and Docker

In development, the typescript code is run with node (--strip-types). However, the production build is bundled with esbuild. This means you can not leverage node_modules and file system at runtime: reading static files from node_modules, hooking require, etc. will not be possible. This implies to be mindful on libraries (that would read static files from there older), or automatic instrumentation (that hook require).

Running node --run bundle will bundle all of the src/ and node_modules/ code into two files:

  • build/index.js which runs the server
  • build/worker.js which runs the task scheduler's worker

This results in super small Docker images that are fast to deploy: the production image only contains alpine, node, env files and the bundle files — no node_modules folder. The one tradeoff is that dependencies cannot base their code on a file structure containing a node_modules folder (typically used to find static files).

Commands:

  • bundle: creates the build/ directory containing the entrypoints and shared code
  • start:prod: runs the http server entrypoint
  • worker:prod: runs the worker entrypoint

Tests

TypeScript Library Starter uses Node.js's native test runner. Coverage is done using c8 but will switch to Node.js's one once out.

Commands:

  • test: runs test runner for both unit and integration tests
  • test:watch: runs test runner in watch mode
  • test:coverage: runs test runner and generates coverage reports

Format & lint

This template relies on Biome to format and lint. It also uses cspell to ensure correct spelling.

Commands:

  • lint: runs Biome with automatic fixing
  • lint:check: runs Biome without automatic fixing (used in CI)
  • spell:check: runs spell checking

Releasing

Under the hood, this service uses semantic-release and Commitizen. The goal is to avoid manual release processes. Using semantic-release will automatically create a GitHub release (hence tags) as well as an npm release. Based on your commit history, semantic-release will automatically create a patch, feature or breaking release.

Commands:

  • cz: interactive CLI that helps you generate a proper git commit message, using Commitizen
  • semantic-release: triggers a release (used in CI)