How to distribute Go binaries with NPM

by Clelia Astra Bertelli

2025-09-27


NPM is a foundational piece of modern software development, since it’s the registry (and package manager) that stores all the packages for JavaScript and Typescript world.

Despite clearly being oriented toward the JS/TS world, NPM can also be used to distribute binaries from other languages, like Go, Rust or C/C++.

In this article, I would like to walk you through how you can easily release a Go package and distribute it through npm, thanks to an extremely useful utility called go-npm.

To do so, we’ll follow these steps:

Without further ado, let’s dive in!

1. Create a Hello World in Go

If you’re interested in this tutorial, you probably already know Go, but, assuming you don’t, let’s create a very simple ‘hello world’ script that we will save under main.go:

package main

import "fmt"

func main() {
    fmt.Println("Hello world!")
}

In order to build and run this Go script, you simply need to run:

go build . -o hello-world
./hello-world

And you will get a nice Hello world printed out on the console.

2. Create a .goreleaser.yaml

GoReleaser is an extremely useful utility to publish Go binaries on platforms such as GitHub.

In order to run it, you simply need to add a .goreleaser.yaml file in the root directory of the Go program you want to build.

Here is an example for our hello world:

builds:
  - binary: hello-world
    goos:
      - windows
      - darwin
      - linux
    goarch:
      - amd64
      - arm64

As you can see, we specify:

Once this is configured, you will be able to automate the builds of your binary effortlessly.

3. Create a package.json

package.json is the file that is used to specify package information for NPM packages. Specifically, in our package.json we will specify:

Here is an example of the package.json file for our hello world project:

{
  "name": "@namespace/hello-world", // change @namespace to your actual namespace!
  "version": "0.1.0",
  "description": "My first Go project published on NPM!",
  "main": "index.js",
  "scripts": {
    "postinstall": "golang-npm install",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/your-name/hello-world.git" // change your-name to your actual GitHub username!
  },
  "keywords": [
    "hello world",
    "go",
    "npm",
    "tutorial"
  ],
  "author": "Your Name",
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/your-name/hello-world/issues"
  },
  "homepage": "https://github.com/Ayour-name/hello-world#readme",
  "dependencies": {
    "golang-npm": "^0.0.6"
  },
  "goBinary": {
    "name": "hello-world",
    "path": "./bin",
    "url": "https://github.com/your-name/hello-world/releases/download/v{{version}}/git-push-blog_{{version}}_{{platform}}_{{arch}}.tar.gz"
  }
}

4. Automate with a GitHub Action

Once we have everything in place, we can automate the publishing with a GitHub Action that runs every time we push a tag to it.

Here is the code, that you should save under .github/workflows/release.yml:

name: Release
on:
  push:
    tags:
      - "v*.*.*"

permissions:
  contents: read # for checkout

jobs:
  release:
    name: Release
    runs-on: ubuntu-latest
    permissions:
      contents: write # to be able to publish a GitHub release
      issues: write # to be able to comment on released issues
      pull-requests: write # to be able to comment on released pull requests
      id-token: write # to enable use of OIDC for npm provenance
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: "lts/*"

      - name: Install goreleaser
        run: npm i -g @goreleaser/goreleaser

      - name: Release Go binary
        run: goreleaser release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Setup npm authentication
        run: echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc
        env:
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

      - name: Release NPM package
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
        run: npm publish --access public

As you can see, in this action we:

5. Test the Release Pipeline

Once you are ready, create a GitHub repository under your-name/hello-world and push all the code you just wrote to the main branch.

Once that is set, you can run:

git tag v0.1.0
git push origin v0.1.0

This way, GitHub will kick off the release action and, in a couple of minutes, you will be able to see the release on GitHub and the package on NPM.

You can then test it by installing it with:

npm install @namespace/hello-world
hello-world # the binary should be available globally

And you’re done: you’ve successfully built, pushed and installed your first Go binary with NPM!