forge-npm-pkg
v2.4.3
Published
A CLI tool to scaffold production-ready npm packages with modern best practices
Maintainers
Readme
forge-npm-pkg
A powerful CLI tool to scaffold production-ready npm packages with modern best practices.
Features
- Interactive CLI with beautiful prompts
- Always-latest package versions - Dynamically fetches current versions from npm registry
- Automatic Node.js LTS detection - Uses current LTS versions for CI and engines
- TypeScript or JavaScript support
- Multiple module formats: ESM, CommonJS, or Dual (both)
- Built-in testing with Vitest or Jest
- ESLint + Prettier for code quality
- GitHub Actions CI/CD workflows (optional)
- Automated publishing with simple tag-based workflow
- Test coverage tracking with Codecov (optional)
- Automated dependency updates with Dependabot (optional)
- User configuration storage (save author info for future projects)
- Package export validation with
@arethetypeswrong/cli - Proper
package.jsonexports configuration - Git repository initialization
- Smart version warnings - Alerts about brand new packages that might be unstable
Usage
Create a new package
npx forge-npm-pkg my-awesome-packageOr without specifying a name (you'll be prompted):
npx forge-npm-pkgWhat Gets Generated?
The CLI will ask you several questions and generate a complete project structure:
Questions
- Language: TypeScript or JavaScript
- Module Format: ESM (Modern), CommonJS (Legacy), or Dual (ESM + CJS)
- Test Runner: Vitest, Jest, or None
- Linting: Initialize ESLint + Prettier?
- Git: Initialize a new git repository?
- CI/CD: Set up GitHub Actions workflows?
- Coverage: Upload test coverage to Codecov? (optional, requires tests)
- Dependencies: Set up Dependabot for automated dependency updates? (optional)
Generated Structure
my-awesome-package/
├── src/
│ ├── index.ts (or .js)
│ └── index.test.ts (if testing enabled)
├── .github/
│ ├── workflows/
│ │ ├── ci.yml (if CI enabled)
│ │ ├── publish.yml (if CD enabled)
│ │ └── dependabot-auto-merge.yml (if Dependabot enabled)
│ └── dependabot.yml (if Dependabot enabled)
├── package.json
├── tsconfig.json (if TypeScript)
├── tsup.config.ts (if TypeScript)
├── vitest.config.ts (if Vitest selected)
├── jest.config.ts (if Jest selected)
├── eslint.config.js (if linting enabled)
├── .prettierrc (if linting enabled)
├── .gitignore
└── README.mdThe Generated Package
Your generated package will have:
Scripts
npm run build- Build the package with tsupnpm test- Run testsnpm run lint- Lint your codenpm run format- Format code with Prettiernpm run check:exports- Validate package exportsnpm run typecheck- Type-check TypeScript (if applicable)
Best Practices
- Proper Package Exports: The
package.jsonincludes correctly configuredexportsfield for maximum compatibility - Type Safety: TypeScript with strict mode enabled
- Testing: Pre-configured testing framework with example tests
- Code Quality: ESLint and Prettier with sensible defaults
- CI/CD: GitHub Actions workflow for automated releases
- Module Formats: Support for ESM, CommonJS, or both (dual)
Module Format Details
ESM (Recommended)
Modern ECMAScript modules with import/export syntax.
{
"type": "module",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
}
}
}CommonJS
Legacy Node.js module format with require().
{
"type": "commonjs",
"exports": {
".": {
"types": "./dist/index.d.ts",
"require": "./dist/index.js"
}
}
}Dual (Maximum Compatibility)
Exports both ESM and CommonJS for maximum compatibility.
{
"type": "module",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.js"
}
}
}Complete Workflow Guide
This section walks you through the entire process of creating and publishing an npm package with automated CI/CD.
1. Initial Setup
Create your package with automated publishing enabled:
npx forge-npm-pkg my-awesome-packageSelect these options:
- Language: TypeScript (recommended)
- Module format: ESM (modern)
- Test runner: Vitest (fast & modern)
- Linting: Yes (ESLint + Prettier)
- Git: Yes (initialize repository)
- CI: Yes (run tests on every push)
- CD: Yes (automated publishing)
The tool will:
- ✓ Create project structure
- ✓ Install dependencies
- ✓ Initialize git repository
- ✓ Create GitHub Actions workflows (CI + Publish)
- ✓ Run initial build to verify setup
- ✓ Optionally create GitHub repository (if
ghCLI is available)
2. Create GitHub Repository
If you have the GitHub CLI installed and authenticated, the tool will prompt you to create a GitHub repository automatically:
◆ Create GitHub repository?
│ ○ Public repository
│ ○ Private repository
│ ● Skip - I'll create it manuallyIf you skip or don't have gh CLI:
cd my-awesome-package
# Create repository on GitHub (using GitHub CLI)
gh repo create my-awesome-package --public --source=. --remote=origin --push
# Or manually:
# 1. Go to https://github.com/new
# 2. Create repository named "my-awesome-package"
# 3. Add remote and push:
git remote add origin https://github.com/yourusername/my-awesome-package.git
git branch -M main
git push -u origin main3. Add NPM Token to GitHub
To enable automated publishing, you need to add your npm token to GitHub:
A. Create NPM Access Token:
- Go to npmjs.com
- Click your profile → Access Tokens
- Click "Generate New Token" → "Classic Token"
- Select type: Automation (for CI/CD)
- Copy the token (starts with
npm_...)
B. Add Token to GitHub:
# Using GitHub CLI (recommended)
gh secret set NPM_TOKEN
# Or manually:
# 1. Go to https://github.com/yourusername/my-awesome-package/settings/secrets/actions
# 2. Click "New repository secret"
# 3. Name: NPM_TOKEN
# 4. Value: [paste your npm token]
# 5. Click "Add secret"💡 Tip: If you need to view your npm token locally, use:
npm run tokenThis displays your .npmrc file contents, making it easy to copy the token for CI/CD setup.
4. Develop Your Package
Write your code:
// src/index.ts
export function greet(name: string): string {
return `Hello, ${name}!`;
}
export function add(a: number, b: number): number {
return a + b;
}Write tests:
// src/index.test.ts
import { describe, it, expect } from 'vitest';
import { greet, add } from './index.js';
describe('greet', () => {
it('should return a greeting message', () => {
expect(greet('World')).toBe('Hello, World!');
});
});
describe('add', () => {
it('should add two numbers correctly', () => {
expect(add(2, 3)).toBe(5);
});
});Run tests locally:
npm test # Run tests
npm run build # Build package
npm run typecheck # Type checking
npm run lint # Lint code5. Commit and Push Changes
git add .
git commit -m "feat: add greet function"
git pushWhat happens automatically:
- ✓ GitHub Actions runs CI workflow
- ✓ Tests are executed
- ✓ TypeScript type checking runs
- ✓ Linting checks run
- ✓ Build is verified
6. Create a Release (Version Bump)
When you're ready to publish to npm:
# Bump version based on change type
npm version patch # Bug fixes: 1.0.0 → 1.0.1
npm version minor # New features: 1.0.0 → 1.1.0
npm version major # Breaking changes: 1.0.0 → 2.0.0
# Push the tag
git push && git push --tagsWhat happens automatically when you push the tag:
- ✓ GitHub Actions publish workflow triggers
- ✓ Dependencies are installed
- ✓ Tests are executed
- ✓ Build runs
- ✓ Package is published to npm 🎉
7. Verify Publication
# Check npm
npm view my-awesome-package
# Install in another project
npm install my-awesome-package8. Ongoing Development Workflow
For every new feature or bug fix:
# 1. Make changes
vim src/index.ts
# 2. Write tests
vim src/index.test.ts
# 3. Run tests locally
npm test
# 4. Commit and push
git add .
git commit -m "fix: resolve edge case in greet()"
git push
# 5. Wait for CI to pass
# 6. When ready to release:
npm version patch # or minor/major
git push && git push --tags
# 7. Package auto-publishes to npm!Common Scenarios
Multiple Changes Before Release
You can commit multiple changes before creating a release:
# Feature 1
git add .
git commit -m "feat: add multiply function"
git push
# Feature 2
git add .
git commit -m "feat: add divide function"
git push
# Bug fix
git add .
git commit -m "fix: handle negative numbers"
git push
# All CI checks pass, now release
npm version minor # Bump version for new features
git push && git push --tags # Auto-publishes to npmAll changes since the last release will be included.
Emergency Patch Release
# Fix critical bug
vim src/index.ts
npm test
# Push immediately
git add .
git commit -m "fix: critical bug in production"
git push
# Wait for CI to pass, then release
npm version patch
git push && git push --tags
# Package publishes automaticallyManual Version Release
If you need to publish manually (bypass CI/CD):
# Build and publish
npm run build
npm publish --access publicWorkflow Diagram
┌─────────────────────────────────────────────────────────┐
│ 1. Developer writes code + tests │
└────────────────────┬────────────────────────────────────┘
│
┌────────────────────▼────────────────────────────────────┐
│ 2. git commit + git push │
└────────────────────┬────────────────────────────────────┘
│
┌────────────────────▼────────────────────────────────────┐
│ 3. GitHub Actions CI runs (tests, lint, build) │
└────────────────────┬────────────────────────────────────┘
│
┌────────────────────▼────────────────────────────────────┐
│ 4. Developer runs: npm version patch/minor/major │
│ - Bumps version in package.json │
│ - Creates git commit and tag │
└────────────────────┬────────────────────────────────────┘
│
┌────────────────────▼────────────────────────────────────┐
│ 5. git push && git push --tags │
└────────────────────┬────────────────────────────────────┘
│
┌────────────────────▼────────────────────────────────────┐
│ 6. GitHub Actions Publish workflow triggers │
│ - Installs dependencies │
│ - Runs tests │
│ - Builds package │
│ - Publishes to npm │
└─────────────────────────────────────────────────────────┘Troubleshooting
CI fails on push:
- Check GitHub Actions tab for error details
- Run
npm run buildandnpm testlocally first - Ensure all tests pass before pushing
NPM_TOKEN error during publish:
- Verify token is added to GitHub secrets
- Token must be "Automation" type, not "Publish"
- Check token hasn't expired
Publish workflow not triggering:
- Ensure you pushed the tag:
git push --tags - Check tag format matches
v*(e.g., v1.0.0) - Verify
.github/workflows/publish.ymlexists
Package not publishing:
- Check package name is available on npm
- Verify NPM_TOKEN is correct
- Check GitHub Actions logs for error details
- Ensure tests pass before publishing
Configuration Management
User Config Storage
Save your author information once and reuse it for future projects:
# First time - you'll be prompted to save
npx forge-npm-pkg my-package
# Enter your name, email, GitHub username
# Choose "Yes" when asked to save for future projects
# Future runs - config loaded automatically
npx forge-npm-pkg another-package
# Your info is pre-filled!Smart Git Integration:
- Automatically detects git config (user.name, user.email)
- Asks for confirmation: "Use git config: Name ?"
- Only prompts for GitHub username if you confirm
Config Commands:
# View stored configuration
npx forge-npm-pkg --config
# Reset stored configuration
npx forge-npm-pkg --reset-config
# Skip saving config this time
npx forge-npm-pkg my-package --no-saveStorage Location:
- Windows:
C:\Users\{user}\AppData\Roaming\forge-npm-pkg\config.json - Mac/Linux:
~/.config/forge-npm-pkg/config.json
Dynamic Version Management
Always Latest, Zero Maintenance
This tool uses dynamic version fetching to ensure your projects always start with the latest stable package versions.
How It Works
When you run forge-npm-pkg, it:
- Fetches latest versions from npm registry in real-time
- Detects Node.js LTS versions from nodejs.org
- Fetches GitHub Actions versions - Latest major version tags (v5, v6)
- Warns about risky versions (new major releases within 30 days)
- Falls back gracefully if network issues occur
What You Get
Latest Package Versions:
{
"devDependencies": {
"typescript": "^5.7.2", // ✓ Latest fetched today
"vitest": "^2.1.5", // ✓ Latest fetched today
"eslint": "^9.15.0" // ✓ Latest fetched today
}
}Current Node.js LTS:
{
"engines": {
"node": ">=20.0.0" // ✓ Current LTS requirement
}
}Dynamic CI Matrix:
strategy:
matrix:
node-version: [20, 22] # ✓ Active LTS versionsLatest GitHub Actions:
steps:
- uses: actions/checkout@v5 # ✓ Latest major version
- uses: actions/setup-node@v6 # ✓ Latest major version
- uses: codecov/codecov-action@v5 # ✓ Latest major versionSmart Warnings
If a package was just released, you'll see:
⚠️ Package Version Warnings
⚠️ [email protected] (3 days old)
New major version - may contain breaking changes.
If issues occur, downgrade: npm install typescript@5Benefits
- ✅ No maintenance - Never update hardcoded versions again
- ✅ Always current - Get latest features and security fixes
- ✅ Future-proof - Automatically adopts new Node LTS and GitHub Actions versions
- ✅ Security best practices - Workflows automatically get latest action security patches
- ✅ Safe defaults - Warnings for potentially unstable versions
- ✅ Graceful fallback - Works even with network issues
When Versions Update
You run the tool today (January 2025):
- Generates project with TypeScript 5.7, Vitest 2.1, Node 20 & 22
- GitHub workflows use actions/checkout@v5, actions/setup-node@v6
You run the tool in October 2025:
- Generates project with TypeScript 6.x, Vitest 3.x, Node 22 & 24
- GitHub workflows use whatever versions are latest at that time
- No code changes needed - automatic!
Requirements
- Node.js >= 20.0.0 (current LTS minimum)
- npm, pnpm, yarn, or bun
- Internet connection (for fetching latest versions)
Development
Build this CLI tool
git clone https://github.com/yourusername/forge-npm-pkg
cd forge-npm-pkg
npm install
npm run buildTesting Strategy
This project uses a multi-layered testing approach to ensure quality:
1. Unit Tests (Vitest)
Test individual generator functions and validators:
npm test # Run unit tests once
npm run test:watch # Run in watch mode
npm run test:coverage # Generate coverage report
npm run test:ui # Interactive UI mode2. E2E Tests
Automated end-to-end tests that verify the full CLI workflow:
npm run test:e2e # Creates project, runs build and tests3. Developer Testing (Experience the CLI)
Quick scripts to manually test the CLI flow and UX:
npm run dev:test # Interactive mode - experience all prompts
npm run dev:test:quick # Quick mode with -y flagThese generate projects in .dev-test/ which is auto-cleaned and gitignored.
Why separate dev testing?
- Unit/E2E tests verify correctness
- Dev testing validates UX and flow
- Allows you to experience the CLI as users do
- Quick iteration on prompts and messaging
4. CI/CD (GitHub Actions)
Automated testing on every push:
- Runs on current Node.js LTS versions (dynamically determined)
- Type checking
- Unit tests
- E2E tests
- Coverage reporting
Run All Tests
npm run test:all # Typecheck + Unit + E2ETest locally with npm link
npm link
forge-npm-pkg test-packageRelease Process
This project includes an interactive release automation tool:
npm run releaseThe script provides a beautiful interactive experience with @clack/prompts:
- Check branch - Warns if not on main/master branch
- Check remote - Detects if remote has new commits (e.g., Dependabot)
- Pull if needed - Offers to pull latest changes automatically
- Test - Runs full test suite (typecheck + lint + tests)
- Review - Shows what will be committed
- Commit - Prompts for commit message
- Version - Interactive bump selection (patch/minor/major)
- Push - Pushes commits and tags (triggers CD workflow)
Features:
- ✅ Branch validation - Warns if not on main/master branch
- ✅ Smart remote detection - Catches Dependabot commits before you release
- ✅ Abort anytime with ESC key
- ✅ Comprehensive error handling
- ✅ Helpful error messages with recovery instructions
- ✅ Safe - never leaves repo in broken state
See scripts/README.md for detailed documentation.
Manual alternative:
npm run sync # Pull latest + install + test
npm run test:all # Verify everything passes
git add .
git commit -m "feat: your message"
npm version patch # or minor, or major
git push && git push --tagsWhy This Tool?
Creating a properly configured npm package is complex:
- Module format confusion (ESM vs CJS)
- Incorrect
package.jsonexports - TypeScript configuration
- Build tool setup
- Testing configuration
- CI/CD pipelines
This tool eliminates the guesswork and gives you a production-ready setup in seconds.
License
MIT
Dependency Management Workflow
This project uses Dependabot to automate dependency updates with a smart grouping strategy.
Dependabot Auto-Merge
When you enable Dependabot, the tool generates an auto-merge workflow that:
- Auto-merges patch and minor updates after CI passes
- Requires manual review for major updates (breaking changes)
- Uses squash merge for clean git history
Required GitHub Settings:
To enable auto-merge, configure these settings in your repository:
Enable auto-merge:
- Settings → General → Pull Requests → ✅ Allow auto-merge
Allow GitHub Actions to approve PRs:
- Settings → Actions → General → Workflow permissions
- ✅ Allow GitHub Actions to create and approve pull requests
Once configured, Dependabot PRs for patch/minor updates will automatically merge after CI passes.
Dependabot Configuration
Dependencies are grouped for easier management:
- Production dependencies: Individual PRs for careful review (critical changes)
- Development dependencies: Grouped into single weekly PR (reduces noise)
- GitHub Actions: Grouped into single weekly PR
This reduces PR volume while keeping production dependencies separate for safety.
Handling Dependabot Updates (Solo Developer Workflow)
When Dependabot creates PRs while you're working locally:
Push your local work first
git add . git commit -m "your changes" git pushMerge Dependabot PR on GitHub
- Review and merge via GitHub UI
- Don't worry about your local state
Sync your local repository
npm run syncThis runs:
git pull --rebase && npm install && npm testOr use
npm run sync:quickto skip tests (faster):npm run sync:quickIf package-lock.json changed, commit and push
git add package-lock.json git commit -m "chore: update package-lock.json after merge" git push
Why This Workflow Works
- Push first: Ensures your work is safe on remote before merging external changes
- Merge on GitHub: Clean, conflict-free merge since you have no local uncommitted work
- Sync script: Automates the pull + install + test sequence
- No surprises: Explicit, transparent, and easy to understand
Contributing
Contributions are welcome! Please open an issue or PR.
