Published on 4 min read
npm - Understanding Scoped Packages
One of the mandatory fields that an npm package must have is a name:
"name": "sample-package"
The name should be unique, thereby representing the package when it’s published to the npm registry.
However, in case that a package is already published with a specific name, whether by another user or organization, clearly it’s not possible to publish our package with this name.
So, we can think about a different name and rename our package, but there’s another option to know about - and this is what we’re going to introduce. 😉
The content is available as a video as well:
What are Scoped Packages?
Scoped packages are a way to group related npm packages under a shared “scope”, that acts pretty much like a namespace.

This kind of packages provides a few benefits:
- We don’t have to worry if the package name exists - just name it, as long as we haven’t already published such a scoped package before
- We don’t have to worry that someone else will publish into our scope - only scope members have the permission
- In case we work with a private npm registry - we don’t have to switch to it before installing or publishing a package, but rather simply set the scope’s private registry once, in advance
That being said, there’s no free lunch, and we need to know how to use them correctly, but that’s the purpose of this guide.
So, let’s demonstrate how to work with scoped packages practically.
Creating a Scope
In order to create a new local scoped package, we can use npm init --scope=sample-scope, which creates a package.json file and names the package considering the provided scope:
"name": "@sample-scope/sample-package"
Notice the convention: the scope name begins with @ and is followed by a slash.
In case the package has already been initialized, we will just need to rename it to contain the scope according to the convention, nothing more.
Publishing the Package
Now that we have an initialized local scoped package, we’d like to communicate with an npm registry to publish this package (and install as well later). Basically there are two options for choosing a registry to publish into - it could be the primary of npm or a private registry which we maintain ourselves.
In case we do want to assign the scope with a private registry, we can use npm config command and set it in advance:
npm config set @sample-scope:registry http://sample-registry.com
Great, let’s communicate with the registry and publish our package.
In order to do that, we should merely run the npm publish command:
npm publish
Having said that, we should be aware that the package is published privately by default, meaning with restricted access.
The thing is we cannot publish privately into the primary registry, unless we have a paid account. So we can change the package to be published publicly when we initially publish with the access argument:
npm publish --access public
If we do want to publish privately, we can upgrade our account to a paid individual or organization; or just maintain our own private registry, for example, using Verdaccio.
Installing the Package
Well, after the scoped package is published, we can easily install it in another project.
All we need to do is running npm install with the full package name including the scope name:
npm install @sample-scope/sample-package
This makes npm install packages of that scope only from the associated registry - there is no fallback to the default registry.
Wrapping Up
Today we explored the scoped packages in npm and focused on its benefits. We learned to associate a registry with the scope, publish a package and install it in another project.
You’re welcome to share:
Join My Newsletter
Get new posts directly to your inbox.
Comments are powered by DisqusDetails
Loading comments activates Disqus, which collects information as a third-party service.
The site owner has no access to or control over the information collected by Disqus.
Related Posts

How to Sync a Design System with Claude Design
18 min read
Syncing React components into Claude Design with /design-sync: what the mirror holds, how it's verified and a step-by-step example with shadcn/ui, Tailwind v4 and Storybook.

ECMAScript - Introducing Deferred Module Evaluation with import defer
8 min read
Introducing the “import defer” proposal, a new ECMAScript import form that loads and links modules eagerly while deferring their evaluation until a namespace property is first accessed - currently at stage 3 in the TC39 process.

ECMAScript - Introducing BigInt Primitive in ES2020 (ES11)
5 min read
BigInt in ES2020 (ES11) - a new primitive for arbitrarily large integers, with its operators, comparisons and limits.