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

@alexstormwood/gha-npm-publishing-demo

v1.0.4

Published

Demo project to showcase automatic NPM package publishing using the newly-required OIDC auth flow.

Downloads

23

Readme

@alexstormwood/gha-npm-publishing-demo

Demo project to showcase automatic NPM package publishing using the newly-required OIDC auth flow.

Problem

Publishing things can be very manual. Automation is our friend, and makes publishing easier!

However, NPM recently made some authentication changes to their systems. Now we have to keep in mind these facts:

  • NPM packages are most-secure when published via a "Trusted Publisher" workflow, such as a git platform's continuous integration (CI) system (e.g. GitHub Actions for GitHub). Trusted publishing can only be configured on existing NPM packages, since it requires an update to a package's settings. If a package doesn't exist yet, it has no settings to edit!
  • This also means that new NPM packages cannot be created via a "Trusted Publisher" workflow, so you must do some manual, human-involved process to initialise a new package on NPM.

We can make granular access tokens in NPM 4 times per year and use those tokens in NPM publishing automation, and may want to do that to at least initialise a new package. But we shouldn't aim to use that for ongoing publishing of a package's new versions, as security/compliance features like package publishing provenance reports don't happen if you are not using Trusted Publishing.

We can also publish packages manually, from our local command line... but that kinda defeats the whole point of even glancing at CI platforms such as GitHub Actions.

It's kinda dumb right now, but it also kinda makes sense:

  • Initialise a new package with human involvement.
  • Configure automation infrastructure for that new package now that the package exists, not before it exists.
  • Never manually be involved in package publishing for that specific package again.

Solution

Repository Setup

  1. Make a new repository on GitHub via its web interface, with a name like gha-npm-publishing-demo.
  2. Clone the project to your programming environment.

NPM Setup

  1. Log in to NPM, making an account if you don't have on already.
  2. Go to your account's Access Tokens page from the profile menu:

NPM profile menu.

  1. From the Access Tokens page, we want to generate a new token. This should be a "granular access token", the only type that NPM allows any more. For the token configuration:
  • Name: Something easy for you to remember, such as GitHub Actions Publisher 1-Day
  • Description: Something easy for you to remember, such as For manually or semi-manually publishing an NPM package, such as a new package's first version.
  • Bypasss two-factor authentication: Tick this box. If we want to use this token in a CI workflow, then we cannot have 2FA enabled for this token.
  • Allowed IP ranges: Skip this, as finding the IP addresses of your GitHub Actions runners can be a pain and doesn't help for creating the first version of an NPM package.
  • Packages and Scopes Permissions: Read and Write, all packages
  • Organizations Permissions: Only relevant if you're publishing packages to an NPM organisation. If you need it, set it to Read and Write for the relevant organisation.
  • Expiration: Pick a custom date 1 day from the day that you're making this token.
  1. Save that NPM token to a text file for now, we'll need it shortly.

  2. Go to your repository's webpage in GitHub and open its Settings section.

  3. Navigate to the "Secrets and variables" heading in the Settings section, which should be under the "Security" subheading.

  4. Create a new secret variable in your Actions section.

  5. Name the secret something recognisable such as "NPM_AUTH_TOKEN, and give it the contents of the NPM token you've just made.

  6. Save the secret to GitHub, and delete the local text file containing the NPM token. The token should only be used by one thing - GitHub Actions.

GitHub settings and secrets.

Project Setup

  1. Run npm init -y to initialise the project as a NodeJS project.
  2. Modify the package.json file so that its name field is scoped to an account or team or organisation that you have publishing permissions to in NPM, such as "name": "@alexstormwood/gha-npm-publishing-demo", - using your GitHub username and ensuring that your GitHub username matches your NPM username keeps this simple.
  • (Optional) Read up on how scoped or namespaced packaging is helpful with resources like these:
    • Karrys, L., & Thomson, E. (2023, October 23). About scopes | npm Docs. Npmjs.com. https://docs.npmjs.com/about-scopes
  1. Modify the package.json file so that its main field will match a soon-to-exist JavaScript file in a src directory, such as "main": "src/index.js",
  2. Create the src directory and an empty index.js file within that src directory, matching the main field you just edited from the package.json.
  3. Add some "whatever" code to that just-made JavaScript file. The code should export something, so we can confirm if the package functionality works as intended later. Code like this is great:
let wordOfTheDay = "bananas";
function getWotD(){
  return wordOfTheDay;
}

module.exports = {
  wordOfTheDay,
  getWotD	
}
  1. Modify the package.json file so that it gains an exports field, with content like this:
  "exports": {
    ".":"./src/index.js"
  },
  • (Optional) Read up about the concept of "entry points" and what that looks like in more-complex NPM/NodeJS projects here:
    • Modules: Packages | Node.js v25.2.1 Documentation. (2025). Nodejs.org. https://nodejs.org/api/packages.html#package-entry-points
  1. Create a .github directory at the root of the repository (e.g. the same level as the src directory, they are sibling directories).
  2. Create a workflows directory within the .github directory.
  3. Create a cd_npm.yml file within the workflows directory. This will be processed as a GitHub Actions workflow because it's a YAML file in a .github/workflows/ directory path.
  4. Add this code to the cd_npm.yml file:
name: CD NPM

on:
  workflow_dispatch:

permissions:
  id-token: write  # Required for OIDC
  contents: read


jobs:
  npm-publisher:
    runs-on: ubuntu-latest
    
    steps:
    - name: Checkout the repo
      uses: actions/checkout@v6
    
    - uses: actions/setup-node@v6
      with:
        registry-url: 'https://registry.npmjs.org/'
        node-version: 24

    - name: Install project dependencies
      run: npm install

    - name: Build the package
      run: npm run build --if-present

    - name: Publish the package
      if: ${{ success() }}
      run: NODE_AUTH_TOKEN="" npm publish --access public --provenance
  1. Create a first_publish_npm.yml file within the workflows directory. This will be processed as a GitHub Actions workflow because it's a YAML file in a .github/workflows/ directory path.
  2. Add this code to the first_publish_npm.yml file:
name: NPM Package First-Time Publish

on:
  workflow_dispatch:

permissions:
  contents: read


jobs:
  npm-publisher:
    runs-on: ubuntu-latest
    
    steps:
    - name: Checkout the repo
      uses: actions/checkout@v6
    
    - uses: actions/setup-node@v6
      with:
        registry-url: 'https://registry.npmjs.org/'
        node-version: 24
        token: ${{secrets.NPM_AUTH_TOKEN}}

    - name: Install project dependencies
      run: npm install

    - name: Build the package
      run: npm run build --if-present

    - name: Publish the package
      if: ${{ success() }}
      run: NODE_AUTH_TOKEN=${{ secrets.NPM_AUTH_TOKEN}} npm publish --access public
  • Note the differences between the two workflows:
    • cd_npm has provenance functionality, and interacts with an id-token permission. This is related to the OIDC stuff that we must set up soon to enable Trusted Publishing - it won't work just yet.
    • first_publish_npm has no provenance or id-token things, but does have a NODE_AUTH_TOKEN value. The cd_npm workflow specifically sets that to a blank string, as it sometimes causes issues with OIDC functionality - but it's the key to manually publishing that first version of our new NPM package to NPM, so we need it in first_publish_npm!
  1. Save and commit your changes to your repository.
  2. Push your repository's commits to the remote repository (which already exists if you made your new repository via the GitHub website).

Enabling Trusted Publishing

  1. First of all: Trusted Publishing - as a system - cannot create new packages. So, navigate to the GitHub repository's Actions section, click through to your "NPM Package First-Time Publish" action, and click its "Run workflow" manual dispatcher button. Let it run - if your NPM token as configured properly and added to the repository as a secret, it will allow the "NPM Package First-Time Publish" action to create a new NPM package.

  2. Visit your new NPM package on the NPM website. Find its Settings page.

  3. Find the "Trusted Publisher" section of your NPM package's settings. Click through to your chosen provider - for this demo project, it's GitHub Actions.

NPM Trusted Publisher settings intro screen

  1. Fill out the "Trusted Publisher" settings as appropriate for your repository. For example:

NPM Trusted Publisher settings form screern.

  1. Click "Set up connection" on that NPM Trusted Publisher screen to finish setting things up. You should be asked for a 2FA code, too - do that.

  2. Jump back to your repository code and bump the version of the project in the project's package.json file. A singular NPM package cannot have two releases with the same version - change its right-most number to be a "1", so the full version field should look like: "version": "1.0.1",

  3. Save, commit, and push the local changes to the remote repository.

  4. Jump back to your GitHub repository's Actions section, and find the "CD NPM" action. From there, click its "Run workflow" manual dispatcher button. Let it run.

Confirming The Package Works

  1. Make a new NodeJS project and do the usual npm init setup stuff.

  2. Run npm install @alexstormwood/gha-npm-publishing-demo or the equivalent using your own published package.

  3. Write this code, run this code, enjoy:

const ghaPackage = require("@alexstormwood/gha-npm-publishing-demo");

console.log(ghaPackage.getWotD());
console.log(ghaPackage.wordOfTheDay());

Common Problems When Setting This Up

  • Older versions of NodeJS in the GitHub Actions runners don't have the right NPM to deal with this new OIDC way of doing things. Specify NodeJS 24 when setting up NodeJS in the job runners.
  • Trusted Publisher configuration is specific - capitalisation and special characters matter! No "@" in organisation or usernames, no character cases that don't exactly match the target name.
  • That package version property in the package.json file must always be some semver increment above the previously-published version of the package.

More-Real Usage

Honestly, this just comes down to triggers for your workflows and things like CI/CD environment configuration. Go nuts. That stuff is beyond the scope of this repository. Look at other open-source projects to see what type of CI/CD they implement, and what type of events or triggers they use to publish their packages.