Scaffold TypeScript npm packages using this template to bootstrap your next library.
Built with ESBuild for blazing fast builds and Rollup for bundled type definitions with watch mode support.
Use this template via GitHub's "Use this template" button or:
gh repo create <name> --template="https://github.com/jasonsturges/esbuild-typescript-npm-package"
Important: Check package name availability before you start to avoid renaming later:
npm search <term>
The following tasks are available:
npm run build
- Build production distributable (JS + types)npm run dev
- Watch mode for both JS and types (rebuilds on file changes)npm run serve
- Start dev server at http://localhost:3000 with live examplesnpm run build:js
- Build only JavaScript bundles (all formats)npm run build:types
- Build only TypeScript declarations (single bundled .d.ts)
This template builds multiple distribution formats:
- ESM (
dist/index.es.js
) - Modern ES modules - CommonJS (
dist/index.cjs.js
) - Node.js compatibility - UMD (
dist/index.umd.js
) - Universal module definition - IIFE (
dist/index.iife.js
) - Browser global variable - Types (
dist/index.d.ts
) - Single bundled TypeScript declaration file
Export everything from the top-level index.ts
for inclusion in the build.
For example, if you have a utils/
folder with an arrayUtils.ts
file:
// src/utils/arrayUtils.ts
export const distinct = <T>(array: T[] = []) => [...new Set(array)];
Include that export in the top-level index.ts
:
// src/index.ts
export { distinct } from "./utils/arrayUtils"
Multiple strategies for development are available.
The examples/
folder provides a local development environment with a dev server:
npm run serve
This starts a dev server at http://localhost:3000 with:
- Live rebuilding on file changes
- Serves static assets from the
examples/
folder - Perfect for rapid prototyping and testing
Edit examples/index.ts
to test your library. Only exports from src/index.ts
are included in the production build.
For development with npm link
or when working with other projects:
npm run dev
This runs both JavaScript and TypeScript builds in watch mode, automatically rebuilding on file changes. Both JS and types are rebuilt, making this ideal for linked package development.
To test your library in other projects before publishing:
-
From this library: Start watch mode and link the package
npm run dev npm link
-
From your app: Link to this library
npm link "mylib"
A symlink is created in your app's node_modules/
. Changes to your library are automatically rebuilt and reflected in your app.
From you library, pack it to create a tarball:
npm pack
This will create a [name].tgz tarball that includes the result of what will be uploaded to npm.
Install the pack file in a test app:
npm install [name].tgz
Once development completes, unlink
both your library and test app projects.
- From your app: run
npm unlink "mylib"
oryarn unlink "mylib"
command to remove the library symlink - From your library: run
npm unlink
oryarn unlink
command to unregister the package
If you mistakenly forget to unlink
, you can manually clean up artifacts from yarn
or npm
.
For yarn
, the link
command creates symlinks which can be deleted from your home directory:
~/.config/yarn/link
For npm
, the link
command creates global packages which can be removed by executing:
sudo npm rm --global "mylib"
Confirm your npm global packages with the command:
npm ls --global --depth 0
For your app, simply reinstall dependencies to clear any forgotten linked packages. This will remove any symlinks in the node_modules/
folder.
Update your package.json
to the next version number and tag a release.
Assure that your package lockfile is also updated by running an install. For npm, this will assure the lockfile has the updated version number. Yarn does not duplicate the version number in the lockfile.
Assure either a .npmrc
or publishConfig
in your package.json
:
package.json:
"publishConfig": {
"registry": "https://registry.npmjs.org/",
"scope": "username"
"access": "public",
}
If you are publishing to a private registry such as GitHub packages, update your package.json
to include publishConfig
and repository
:
package.json:
"publishConfig": {
"registry": "https://npm.pkg.github.com/@MyOrg"
}
Before publishing, ensure a clean build:
rm -rf dist
npm run build
Verify your package name is available:
npm search <term>
Once ready to publish:
npm login
npm publish --access public
For continuous integration with GitHub Actions, create a .github/workflows/publish.yml
For public NPM packages, use the following workflow:
name: Publish Package to npmjs
on:
release:
types: [created]
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
registry-url: 'https://registry.npmjs.org'
- run: npm ci
- run: npm run build
- run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
For private GitHub packages, use the following workflow:
name: Publish Package to GitHub Packages
on:
release:
types: [created]
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
registry-url: "https://registry.npmjs.org"
scope: "@MyOrg"
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: npm ci
- run: npm run build
- run: npm publish
This will deploy your build artifact when a release is tagged.
Obtain an "Automation" CI/CD access token to bypass 2FA from npm by selecting your profile image in the upper right, and chosing "Access Tokens".
To add secrets to your repository:
- From your repository, select Settings
- From the Security section of the sidebar, expand Secrets and variables and select Actions
- From the Secrets tab, press New repository secret to add the
NPM_TOKEN
key
To add secrets to your organization:
- From your organization, select Settings
- From the Security section of the sidebar, expand Secrets and variables and select Actions
- From the Secrets tab, press New organization secret to add the
NPM_TOKEN
key
For more information, see: