npm: Publishing Packages
Authentication
# Login to npm registry
npm login # prompts for username/password/OTP
npm login --scope=@myorg # login for org scope
# Check current user
npm whoami
# Logout
npm logout
# Use access token (for CI)
echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc
# Or set NPM_TOKEN env variable — some registries read it automaticallyPackage Scope & Access
Unscoped packages: published as "my-package", globally unique name
Scoped packages: "@myorg/my-package" — org or username prefix, must be published explicitly as public
Public packages: anyone can install. Private packages: npm Pro/Teams required (paid).
GitHub Packages: alternative registry, free for public packages, integrates with GitHub Actions
Preparing to Publish
# Check what will be included in the published package
npm pack --dry-run
npm pack # Creates a .tgz file to inspect
# Verify package contents
tar -tzf my-package-1.0.0.tgz | head -50// Control what's published via "files" field (whitelist)
{
"files": [
"dist",
"README.md",
"!dist/**/*.test.*",
"!dist/**/*.map"
]
}
// Always excluded: .git, node_modules, .npmrc, .env, *.log
// Always included: package.json, README.md, LICENSE, CHANGELOG.mdPublishing
# Publish for the first time
npm publish # defaults to latest tag
npm publish --access public # required for scoped packages
# Publish with a tag (won't be installed by default with @latest)
npm publish --tag beta
npm publish --tag next
# Install specific tag
npm install my-package@beta
npm install my-package@nextVersioning Workflow
# Bump version (updates package.json, creates git tag)
npm version patch # 1.0.0 → 1.0.1
npm version minor # 1.0.0 → 1.1.0
npm version major # 1.0.0 → 2.0.0
npm version 1.2.3 # set exact version
npm version prerelease --preid beta # 1.0.0 → 1.0.1-beta.0
# Typical release workflow
npm run check # lint + test + typecheck
npm run build # compile
npm version patch # bump version, creates git tag
git push && git push --tags
npm publish
# Or use release tools
npx release-it # interactive release workflow
npx changeset # monorepo-friendly changelog managementdist-tags
# Manage distribution tags
npm dist-tag ls my-package # show all tags
npm dist-tag add my-package@1.0.0 latest
npm dist-tag add my-package@2.0.0-beta.1 beta
npm dist-tag rm my-package old-tag
# Users install 'latest' by default:
npm install my-package # installs 'latest' tag
npm install my-package@beta # installs 'beta' tagPackage Deprecation
# Deprecate a version (warning shown on install)
npm deprecate my-package@"< 2.0.0" "Please upgrade to v2.0.0+"
# Deprecate all versions
npm deprecate my-package "This package is no longer maintained"
# Unpublish (only within 72 hours of publish, strict policy)
npm unpublish my-package@1.0.0 # specific version
# After 72h: contact npm support
# Better alternative: deprecate instead of unpublishGitHub Packages Registry
# .npmrc to use GitHub registry for a scope
@myorg:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}
# Publish to GitHub Packages
npm publish --registry https://npm.pkg.github.com
# package.json name must match GitHub org
# "@myorg/my-package" → github.com/myorg/my-packageKeep your own version of these notes — editable, searchable, and organised by your stack.
Start free