How to consume private npm packages in React
Managing dependencies in a professional React environment often requires access to proprietary code stored in private registries.
With over 25 years of experience in software development and as the creator of CoreUI, I have architected numerous internal design systems that rely on private npm packages for secure distribution.
The most efficient and modern solution for consuming these packages is to configure a project-level .npmrc file that utilizes environment variables for authentication tokens.
This approach ensures that your credentials remain secure while allowing your React application to build seamlessly across local environments and CI/CD pipelines.
Use a project-level .npmrc file to define your registry and map an environment variable to your authentication token.
# .npmrc
@my-org:registry=https://registry.npmjs.org/
//registry.npmjs.org/:_authToken=${NPM_TOKEN}
The configuration above tells npm that any package starting with the @my-org scope should be fetched from the official registry (or a private one like GitHub Packages or Verdaccio) using the token provided in the NPM_TOKEN environment variable. This prevents you from hardcoding sensitive keys into your source control, which is a critical security requirement in enterprise React projects.
Best Practice Note:
Always add .npmrc to your repository but ensure the actual token is never committed; instead, inject it during the build process. At CoreUI, we use this pattern for our PRO versions to maintain a balance between ease of installation and strict access control.
1. Setting up the Project-Level .npmrc
The first step in consuming private packages is creating a configuration file at the root of your React project. Unlike the global configuration located in your home directory, a project-specific .npmrc ensures that every developer on your team uses the same settings.
# .npmrc configuration for scoped private packages
# This file should be committed to your version control system
# Define the registry for your specific scope
@coreui-pro:registry=https://registry.npmjs.org/
# Set up the authentication mapping
# We use a variable placeholder to keep the secret safe
//registry.npmjs.org/:_authToken=${NPM_TOKEN}
# Optional: Always auth ensures npm sends the token for every request to this registry
always-auth=true
By defining the scope (e.g., @coreui-pro), you tell the package manager exactly which packages require special permissions. This prevents unnecessary overhead when installing public packages like react or react-dom.
2. Managing the Authentication Token Securely
Security is paramount when dealing with private codebases. You should never paste your plain-text npm token directly into the .npmrc file. Instead, use a local .env file for development and environment secrets for production.
# .env (DO NOT COMMIT THIS FILE)
# Generate this token from your npm profile settings
NPM_TOKEN=npm_000000000000000000000000000000
To make the environment variable available to npm during installation, you might need to export it in your terminal session. If you are using a tool like dotenv in your build script, ensure it is loaded before the package manager runs. Most modern shells and CI environments handle the ${NPM_TOKEN} syntax in .npmrc natively.
3. Configuring Scoped Packages in package.json
Once your authentication is configured, you can add the private package to your package.json. Scoped packages are the standard way to organize private modules in the npm ecosystem.
{
"name": "my-secure-react-app",
"version": "1.0.0",
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0",
"@coreui/react": "^5.0.0",
"@my-org/private-utils": "^1.2.3"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build"
}
}
After adding the dependency, run npm install. The package manager will look at your .npmrc, find the @my-org scope, use the NPM_TOKEN from your environment, and download the package into node_modules.
4. Consuming the Private Package in React Components
Using a private package in your React code is identical to using a public one. The benefit is that you can now share proprietary logic or UI components across multiple internal projects.
import React from 'react'
import { CAlert } from '@coreui/react'
// Importing from our private package
import { formatSecureDate } from '@my-org/private-utils'
const DashboardNotice = () => {
// Example of using a utility from a private package
// Similar to: /answers/how-to-format-date-as-yyyy-mm-dd-in-javascript/
const today = formatSecureDate(new Date())
return (
<div className='p-4'>
<CAlert color='info'>
Welcome back! Today is {today}.
Your private session is active.
</CAlert>
</div>
)
}
export default DashboardNotice
In this example, we utilize a standard CoreUI Alert component alongside a custom formatting utility from our private repository. This maintains consistency while keeping business logic encapsulated.
5. Integrating with CI/CD Pipelines
To build your React application in a CI/CD environment (like GitHub Actions, GitLab CI, or Jenkins), you must provide the NPM_TOKEN to the runner. Here is how you would configure a GitHub Actions workflow.
# .github/workflows/build.yml
name: React Build
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
# This automatically creates a .npmrc file
registry-url: 'https://registry.npmjs.org'
scope: '@my-org'
- name: Install Dependencies
run: npm install
env:
# Inject the secret from GitHub Action Secrets
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Build Project
run: npm run build
The secrets.NPM_TOKEN should be added to your GitHub repository settings under Secrets and Variables. This ensures that even the build logs do not expose your private credentials.
6. Troubleshooting Common Issues
When consuming private packages, you might encounter a “404 Not Found” or “401 Unauthorized” error. This usually indicates a configuration mismatch in the .npmrc or a missing environment variable.
- 404 Error: Often means the scope isn’t correctly mapped to the registry. Double-check that
@your-scope:registryis defined. - 401 Error: This usually means the token is invalid, expired, or the environment variable isn’t being read. Run
echo $NPM_TOKEN(ordir env:NPM_TOKENon Windows) to verify the variable is set in your current shell. - Check if your string contains a substring: If you are dynamically building registry URLs, ensure you are correctly validating them. You can learn how to check if a string contains a substring in JavaScript to verify your environment configurations.
7. Using Private CoreUI PRO Packages
If you are using CoreUI PRO, the process is very similar. Our private packages are hosted on our secure registry to provide you with advanced components and templates.
# Example for CoreUI PRO
@coreui-pro:registry=https://registry.coreui.io/
//registry.coreui.io/:_authToken=${COREUI_PRO_TOKEN}
This setup allows you to keep your Admin Dashboard Template updated with the latest security patches and features without manual downloads. By integrating private npm packages correctly, you transform your React development workflow into a scalable, enterprise-grade architecture.



