DEV Community

Atlas Whoff
Atlas Whoff

Posted on

npm Package Publishing: Versioning, Scopes, and Automation

When to Publish to npm

Publish to npm when:

  • Multiple projects need the same utility code
  • You want to share tools with the community
  • You're building a framework or library

Don't publish for app-specific code—use a monorepo instead.

Package Setup

// package.json
{
  "name": "@yourscope/my-utils",
  "version": "1.0.0",
  "description": "Utility functions for TypeScript projects",
  "main": "./dist/index.js",
  "module": "./dist/index.mjs",
  "types": "./dist/index.d.ts",
  "exports": {
    ".": {
      "import": "./dist/index.mjs",
      "require": "./dist/index.js",
      "types": "./dist/index.d.ts"
    }
  },
  "files": ["dist"],
  "scripts": {
    "build": "tsup src/index.ts --format cjs,esm --dts",
    "prepublishOnly": "npm run build && npm test"
  },
  "publishConfig": {
    "access": "public"
  }
}
Enter fullscreen mode Exit fullscreen mode

Build with tsup

npm install -D tsup typescript
Enter fullscreen mode Exit fullscreen mode
// tsup.config.ts
import { defineConfig } from 'tsup';

export default defineConfig({
  entry: ['src/index.ts'],
  format: ['cjs', 'esm'],
  dts: true,
  clean: true,
  sourcemap: true,
  minify: false, // let consumers minify
});
Enter fullscreen mode Exit fullscreen mode

Semantic Versioning

MAJOR.MINOR.PATCH

1.0.0 — initial stable release
1.0.1 — patch: bug fix, no API changes
1.1.0 — minor: new feature, backwards compatible
2.0.0 — major: breaking change

Pre-release:
2.0.0-alpha.1 — alpha
2.0.0-beta.1 — beta
2.0.0-rc.1 — release candidate
Enter fullscreen mode Exit fullscreen mode
npm version patch  # 1.0.0 → 1.0.1
npm version minor  # 1.0.1 → 1.1.0
npm version major  # 1.1.0 → 2.0.0
npm version prerelease --preid=beta  # → 2.0.0-beta.0
Enter fullscreen mode Exit fullscreen mode

npm version automatically creates a git tag and commits the version bump.

Changesets (Team Workflow)

For packages with multiple contributors:

npm install -D @changesets/cli
npx changeset init
Enter fullscreen mode Exit fullscreen mode
# Developer adds a changeset when making a change
npx changeset
# Select: patch/minor/major
# Write: what changed
# Creates a .changeset/random-name.md file
Enter fullscreen mode Exit fullscreen mode
# Release: consume changesets, bump version, update CHANGELOG
npx changeset version
git commit -am "Version packages"
npm publish
Enter fullscreen mode Exit fullscreen mode

GitHub Actions Auto-Publish

# .github/workflows/release.yml
name: Release

on:
  push:
    tags: ['v*']

jobs:
  publish:
    runs-on: ubuntu-latest
    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 test
      - run: npm publish
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
Enter fullscreen mode Exit fullscreen mode
# Trigger release
git tag v1.1.0
git push origin v1.1.0
# GitHub Actions publishes automatically
Enter fullscreen mode Exit fullscreen mode

Scoped Packages

# Scoped to your npm username or organization
@yourname/package-name
@yourorg/package-name

# Public scoped package (free)
npm publish --access public

# Private scoped package (requires npm paid plan or private registry)
npm publish --access restricted
Enter fullscreen mode Exit fullscreen mode

Scoped packages prevent naming conflicts and group related packages.

What to Include/Exclude

# .npmignore or "files" in package.json

INCLUDE:
  dist/          ← compiled output
  README.md      ← documentation  
  LICENSE        ← required for open source

EXCLUDE:
  src/           ← source TypeScript (unless providing dual)
  test/          ← tests
  .github/       ← CI config
  node_modules/  ← always excluded automatically
  .env           ← NEVER publish this
Enter fullscreen mode Exit fullscreen mode

Testing Before Publish

# Dry run — see what would be published
npm publish --dry-run

# Check package contents
npm pack
tar -tzf *.tgz

# Test locally before publishing
npm link
cd /path/to/other-project
npm link @yourscope/my-utils
Enter fullscreen mode Exit fullscreen mode

The files field in package.json is the most important thing to get right—too broad and you ship source and tests; too narrow and consumers can't import your package.


Need to automate your developer tooling? Whoff Agents Ship Fast Skill Pack includes npm package templates, GitHub Actions workflows, and release automation.

Top comments (0)