Publish an n8n Community Node to npm with Provenance
In this video
This is the written version of Part 7 of Build your own n8n node. The node works, and exactly one person can use it. By the end of this part it's on npm with a provenance badge, and a clean n8n that has never heard of you installs it by name.
There's a newer rule in the way. If you ever want n8n to verify your node, you can't publish it from your laptop any more, and one setting on your GitHub repository decides whether any of it works. People tend to find that out at the very end. You'll know before you start.
Ask the linter first
Before anything goes anywhere, run n8n's linter:
npm run lint
The first time, you get a wall. Dozens of problems. Everybody gets the wall; don't take it personally.
Most of it is small: a description that doesn't end properly, a list of options that should be in alphabetical order, a label with the wrong capitals. It's largely the UX rules from Part 6, checked by a machine. Some of it, the linter fixes for you:
npm run lint:fix
The rest you fix by hand. Then run it again until it comes back clean. VS Code with the ESLint extension shows the same warnings as you type, which is easier than reading them all at the end. Don't edit eslint.config.mjs to make warnings go away; n8n's docs ask you to leave it as the tool wrote it.
Three things in package.json
n8n looks for three things in your package.json:
{
"name": "n8n-nodes-acme-crm",
"keywords": ["n8n-community-node-package"],
"n8n": {
"n8nNodesApiVersion": 1,
"nodes": ["dist/nodes/AcmeCrm/AcmeCrm.node.js"],
"credentials": ["dist/credentials/AcmeCrmApi.credentials.js"]
}
}
- The name starts with
n8n-nodes-, or@scope/n8n-nodes-. We did that in Part 2. - The keywords include
n8n-community-node-package, exactly. It's how n8n finds community nodes on npm at all. - The
n8nblock lists the built node and credential files.
Miss any of the three, and you've published a perfectly good package that nobody can install as a node. While you're in there, fill in description, author, license (MIT, which verification requires) and repository, pointing at your public GitHub repo.
The rule: GitHub Actions and provenance
For years, publishing was npm publish from your laptop. You still can, for a node you never want verified.
But from 1 May 2026, nodes submitted to n8n for verification must be published by a GitHub Actions workflow, with a provenance statement. n8n won't accept verified nodes published directly from a local machine. (n8n's verification guidelines page words this more broadly, as applying to all community nodes. Either way, publishing from GitHub Actions is the safe default.)
What provenance is
When someone installs your node, they install a package from npm. The code is on GitHub, where they can read it. But how do they know the two are the same thing, that what's on npm was really built from that code? Without provenance, they trust you.
Provenance is the proof: a signed statement attached to the package that says "this exact package was built from this exact commit, in this exact repository, by GitHub Actions." GitHub signs it, and anyone can check it.
Think about what a node does. It holds people's API keys. It's a fair rule.
The catch: the repository must be public
Provenance only works if your repository is public. The point is that anyone can go and check it, and a private repository leaves nothing to check against.
Private repository, no provenance. No provenance, no verification. Nothing warns you about this at the start, so if you're heading for verified, make the repository public first.
Let GitHub publish
If you made the project with npm create @n8n/node, it already includes the workflow: .github/workflows/publish.yml. When a version tag is pushed, GitHub builds the package and publishes it with provenance attached. (For an older project, copy publish.yml from n8n's n8n-nodes-starter repository, and make sure @n8n/node-cli 0.23.0 or later is in your devDependencies.)
What's left is telling npm to trust that workflow. The old way was a long-lived npm token pasted into GitHub's secrets, and hoping it never leaked. The new way is trusted publishing, with no token at all:
- Sign in to npmjs.com and open your package's settings.
- Under Publish access → Trusted Publishers, choose Add a publisher.
- Select GitHub Actions and fill in the repository owner, the repository name, and the workflow file name:
publish.yml. That's the file name, not thename:inside it.
Type those exactly. One wrong letter and the publish fails with a message that tells you very little.
Trusted publishers are set in a package's settings on npm, so the package has to exist there. For a very first release, the comments in publish.yml describe the token alternative (a granular access token stored as NPM_TOKEN in the repository's Actions secrets). Check npm's trusted publishing docs for the current first-publish steps.
Publish a release
npm run release
This bumps the version, commits, tags and pushes. The tag starts the workflow. Then you watch a yellow circle spin on GitHub's Actions tab, which is the longest minute of the whole project.
Green. The package is on npm, with the provenance badge on its page. Anybody can install it now.
Install it like a stranger
Always check it the way a stranger would: not in your dev setup, but a clean n8n that has never seen your code.
In a self-hosted n8n: Settings → Community Nodes → Install, type n8n-nodes-acme-crm, tick the box that says you understand the risks of installing community code, and install. Search the nodes panel for "Acme CRM", and there's your node, from the internet this time.
Only the instance owner or an admin can install community nodes. If you don't see the Install button, that's usually why. If the node installs but isn't there, the community node troubleshooting guide covers the usual causes.
What you have now
- a node that passes n8n's linter
- a package published from GitHub with proof of where it came from
- a node a stranger can install by name
For everybody who runs their own n8n, the answer to "Do you support n8n?" is now yes. People on n8n Cloud still can't install it, because Cloud only allows verified community nodes. In Part 8 it gets the badge.
One more thing. The repository, the workflow and the trusted publisher are one step in NativeShip, the tool we build, which publishes the generated package to npm under your own account through its GitHub integration.
Frequently asked questions
Run npm run lint until it's clean, check that package.json has the n8n-nodes- name, the n8n-community-node-package keyword and the n8n block, then release from GitHub Actions with the publish.yml workflow the scaffold created. npm run release bumps the version, tags it and pushes, which starts the workflow.
Since 1 May 2026, nodes submitted to n8n for verification must be published from GitHub Actions with a provenance statement. n8n won't accept verified nodes published from a local machine.
Provenance proves a package was built from a specific commit in a specific repository. Anyone has to be able to check that repository, so it has to be public.
On self-hosted n8n, go to Settings → Community Nodes → Install, type the npm package name, accept the risk notice and install. On n8n Cloud, only verified community nodes can be installed, from the nodes panel.