Building and Publishing TypeScript NPM Packages: A Step-by-Step Guide

📆 · ⏳ 5 min read · ·


Creating and publishing your own Npm packages can be a rewarding experience, allowing you to share your code and contribute to the open-source community. TypeScript, with its static typing and modern language features, is an excellent choice for building high-quality libraries and utilities.

In this tutorial, we will walk through the process of building and publishing an Npm package using TypeScript. We’ll cover the essential steps from project setup to testing, building, and finally releasing the package on NPM.


Before we dive into the tutorial, make sure you have Node.js and NPM installed on your machine. Additionally, a basic understanding of TypeScript and package management with NPM will be helpful.

Setting Up the Project

To begin, let’s set up a new TypeScript project by using a template which will have all the initial boilerplate required like ts-npm-template ↗️ as a starting point.

Clone the template repository or use it as a template directly from Github to initialize your own project.

Note: This template is created by me and follows an opiniated structure for creating NPM packages. I am constantly learning and improving it to adhere to best practices.

What the template includes

  • TypeScript configuration with strict type checking and ES module output.
  • Biome.js for linting and formatting.
  • Vitest for testing your package.
  • Tsup for bundling your code.
  • Changesets for managing versioning and changelogs.
  • Typedoc for automatically generating documentation of your package.
  • Github Actions workflow for automating the testing and release process.
  • PNPM package manager for faster and more efficient dependency management.

So in all the template is feature rich and will help you get started with creating NPM packages with TypeScript. All you need to focus on is writing your library code. Ofcourse, you can always customize the template to suit your needs.

Let’s understand the steps to set up the project using the template.

Steps to set up the project

After you have created a new repository using the template, follow these steps to set up the project

Creating the Package

Start by defining the package details in the package.json file, including the package name, version, author, and other relevant information.

This will be the metadata for your package and will be used when publishing it to NPM.

Writing your library code

Write your library code in TypeScript, taking advantage of its static typing and other language features. Organize your code into modules and export the necessary functions, classes, or objects to be consumed by other developers.

The place to start with is the src/index.ts file. You can follow the example structure which is provided in the template or follow your own structure.

Testing with vitest

Ensuring the quality of your code is crucial the template uses a testing framework like vitest ↗️ to write unit tests for your package.

Write test cases to cover different scenarios and validate the behavior of your library functions. This will help you catch bugs early and ensure that your code works as expected.

Building with tsup

To make your code ready for distribution, you need to bundle it into a single file. The template uses tsup ↗️, a zero-config bundler specifically designed for TypeScript projects.

It will handle the transpilation and bundling process for you, producing a browser-ready JavaScript file. The template is already configured to use tsup with the necessary settings, however you can customize it as per your needs.

The settings enabled are as follows:

  • Output ES module, Common JS and IIFE format.
  • Minify the output.
  • Generate source maps for debugging.
  • Tree shaking

Versioning and Publishing with Changesets

Changesets ↗️ is a tool that helps you manage versioning and changelogs for your package. It allows you to create a new version based on the changes made in your code and automatically update the package.json file.

This project started with using Semantic Release however it was later replaced with Changesets as it provides more control over the versioning process, especially when working with new contributors who might not be familiar with Semantic Release and Conventional Commits.

With Changesets, the workflow looks like this:

  1. Make changes to your code and commit them.
  2. Run pnpm changeset to create a new changeset.
  3. Push the changeset to the repository.
  4. A Github action will run and determine the next version based on the changeset. It will open a PR with the new version and changelog.
  5. Keep adding changesets and merging the PRs, everything will get clubbed into a single release.
  6. Once you are ready to release, merge the PR and the package will be published to NPM.

With these configurations in place, you are all set to start writing your library code and testing it. The template provides a solid foundation for building and publishing NPM packages with TypeScript, allowing you to focus on writing high-quality code and sharing it with the community.


We learned how to create packages using TypeScript and automatically publish them NPM using the template (ts-npm-template ↗️). This will help you get started with creating your own NPM packages with TypeScript.

We went through what the template provides out of the box and how you can customize it to suit your needs. The template is feature rich and will help you focus on writing your library code rather than setting up the project.

If you are someone who is looking to create NPM packages, I would recommend you to use the template as a starting point and if you want to contribute to the template, feel free to raise a PR to improve it.

You may also like

  • I built my own in-house Newsletter system

    Discover how I transformed the need for a newsletter system, sparked by Revue's shutdown, into a fulfilling side project. Dive into the my journey of conceptualizing, breaking down, and building a custom newsletter system that seamlessly integrates with my website's content workflows.

  • Running SSL on Localhost

    In today's digital landscape, security is paramount. Secure Sockets Layer (SSL) is a crucial technology that encrypts data transmitted between a user's browser and a website, ensuring confidentiality and integrity. But did you know you can also enable SSL for your localhost development environment? This guide will walk you through the process step by step.

  • Get Up and Running with the Latest Version of Node.js on Raspberry Pi

    Do you want to run the latest version of Node.js on your Raspberry Pi? This guide will take you through the process of installing the latest version of Node.js on armhf architecture using binary packages.