Building a NPM Package Template Generator

8 min readSargon Piraev

Learn how to create a CLI tool that generates production-ready NPM packages with TypeScript, testing, linting, and CI/CD setup in seconds


Introduction

Creating a new NPM package from scratch involves setting up dozens of configuration files, dependencies, and tooling. What if you could generate a production-ready package structure in seconds? In this post, I'll show you how I built @sargonpiraev/create-npm-package - a CLI template generator that creates fully configured TypeScript NPM packages with all the modern tooling you need.

The Problem: Repetitive Package Setup

Every time I wanted to create a new NPM package, I had to:
- Set up TypeScript configuration
- Configure ESLint and Prettier
- Add testing with Jest
- Set up Git hooks with Husky
- Configure semantic release
- Add CI/CD pipeline
- Set up conventional commits and commit linting

This process was taking hours and was prone to copy-paste errors. After creating several packages manually, I realized I needed a better solution.

The Solution: A Template Generator CLI

What the Template Includes

My @sargonpiraev/create-npm-package provides a complete development environment:

Core Technologies:
- TypeScript with ES modules support
- ESLint with latest TypeScript configuration
- Prettier for consistent code formatting
- Jest for testing with coverage reporting

Development Workflow:
- Husky Git hooks for quality control
- Commitlint enforcing conventional commits
- Semantic Release for automated versioning and publishing
- GitLab CI/CD pipeline ready to deploy

Project Structure:
- Proper src/ directory with TypeScript entry point
- Professional package.json with all necessary scripts
- Complete configuration files for all tools
- MIT license and proper NPM publishing setup

How It Works

The CLI tool works in five simple steps:

1. Argument validation: Takes project name as required argument
2. Directory creation: Creates project folder with conflict detection
3. Template copying: Copies all configuration files from the package
4. Package.json generation: Creates customized package.json with your project name
5. Source setup: Creates src/index.ts starter file

`typescript
#!/usr/bin/env node

import fs from 'fs'
import path from 'path'

// Get project name from command line
const projectName = process.argv[2]
if (!projectName) {
console.error('Error: Please specify a project name.')
process.exit(1)
}

// Create and populate project directory
const projectDir = path.resolve(process.cwd(), projectName)
// ... file copying and setup logic
`

Implementation Deep Dive

Smart File Management

The generator intelligently handles file conflicts:
- Warns if directories or files already exist
- Safely creates nested directory structures
- Handles npm's .gitignore to .npmignore renaming issue

Template File Architecture

Key configuration files included:
`
.husky/ # Git hooks
├── pre-commit # Runs linting before commits
└── commit-msg # Validates commit messages

.gitlab-ci.yml # CI/CD pipeline
commitlint.config.ts # Conventional commit rules
eslint.config.ts # Latest ESLint configuration
jest.config.ts # Testing setup with coverage
tsconfig.json # TypeScript compilation settings
.prettierrc.json # Code formatting rules
.releaserc.json # Semantic release configuration
`

Dynamic Package.json Generation

The generator creates a customized package.json by:
- Extracting proven scripts and dependencies from the template
- Setting the project name from CLI argument
- Preserving all development tooling configuration
- Setting up proper NPM publishing metadata

Real-World Usage Examples

Quick Start

`bash

Create a new package


npx @sargonpiraev/create-npm-package my-awesome-package
cd my-awesome-package

Install dependencies


npm install

Start developing


npm run dev

Run tests


npm test

Build for production


npm run build
`

What You Get Immediately

A complete project ready for:
- Immediate development: TypeScript compilation with watch mode via npm run dev
- Quality control: Automatic linting and formatting on every commit with Husky hooks
- Testing: Jest configured with coverage reporting and XML output for CI
- CI/CD: Complete GitLab pipeline with 4 stages and 6 parallel test jobs
- Publishing: Semantic release automation with conventional commits
- Complete setup: All modern tooling configured and working together

Proven Results

This template has been successfully used to create:

- habitify-api-client: TypeScript client for Habitify API
- habitify-mcp-server: MCP server for Habitify API

Each package generated saved 2-3 hours of initial setup time and ensured consistent tooling across all projects.

CI/CD Pipeline Deep Dive

One of the most valuable features of this template is the production-ready GitLab CI/CD pipeline. Let me break down how it works and why it saves significant development time.

Why GitLab CI?

I chose GitLab CI for this template because it offers an excellent balance of simplicity and power. The YAML configuration is straightforward, everything lives in one place (code, CI/CD, releases), and it has generous free tier for open source projects.

GitHub Integration: If you prefer GitHub, GitLab supports automatic mirroring. You can keep your main repository on GitHub while leveraging GitLab's CI/CD capabilities. I often use this approach myself.

Coming Soon: GitHub Actions support is planned for future releases, giving you more platform options.

Pipeline Architecture

The .gitlab-ci.yml creates a robust 4-stage pipeline:

🔧 Install Stage
`yaml
install:
stage: install
script:
- npm ci --prefer-offline --cache .npm --no-audit --progress=false
artifacts:
paths: [node_modules]
expire_in: 1 day
`

🧪 Test Stage (6 parallel jobs)
- Unit tests: Jest with coverage reporting and XML output
- Code formatting: Prettier validation
- Type checking: TypeScript compiler verification
- Linting: ESLint with TypeScript rules
- Security audit: npm audit for vulnerabilities
- Build verification: Ensures compilation succeeds

📦 Build Stage
`yaml
build:
stage: build
script:
- npm run build
artifacts:
paths: [build]
expire_in: 1 day
`

🚀 Release Stage (main branch only)
`yaml
release:
stage: release
script:
- npx semantic-release
rules:
- if: $CI_COMMIT_BRANCH == "main"
`

Setting Up Your GitLab Project

Before configuring automated publishing, you need to create a GitLab project:

1. Create new project on GitLab:
- Go to [gitlab.com](https://gitlab.com) and click "New project"
- Choose "Create blank project"
- Set project name (same as your package name)
- Set visibility level (Public for open source packages)

2. Push your generated package:
`bash
cd your-package-name
git init
git add .
git commit -m "feat: initial package setup"
git remote add origin https://gitlab.com/yourusername/your-package-name.git
git push -u origin main
`

Setting Up Automated Publishing

After creating your GitLab project, you need two tokens for the pipeline:

NPM_TOKEN for package publishing:
1. Go to [npmjs.com](https://www.npmjs.com) → Account Settings → Access Tokens
2. Create a new Automation token
3. Add to GitLab CI/CD variables as NPM_TOKEN

GITLAB_TOKEN for releases and tags:
1. Go to GitLab → User Settings → Access Tokens
2. Create token with write_repository scope
3. Add to GitLab CI/CD variables as GITLAB_TOKEN

Both tokens should be set as protected and masked variables in your GitLab project settings.

Semantic Release Magic

The pipeline uses semantic-release for intelligent versioning:

- fix: commits trigger patch releases (1.0.1)
- feat: commits trigger minor releases (1.1.0)
- BREAKING CHANGE: triggers major releases (2.0.0)

This automatically:
- Analyzes commit messages following [Conventional Commits](https://www.conventionalcommits.org/)
- Determines the next version number
- Generates changelog from commits
- Creates Git tags and releases
- Publishes to NPM registry

Live Pipeline Example

You can see this pipeline in action:
- [Pipeline execution](https://gitlab.com/sargonpiraev/create-npm-package/-/pipelines/1902470330) - Complete build process
- [Automated releases](https://gitlab.com/sargonpiraev/create-npm-package/-/releases) - Generated releases with changelogs
- [Git tags](https://gitlab.com/sargonpiraev/create-npm-package/-/tags) - Automatic version tags

Why This Pipeline Matters

Zero-effort publishing: Once configured, every merge to main automatically:
- Runs comprehensive quality checks
- Publishes new versions based on changes
- Creates detailed releases with changelogs
- Maintains version history

Quality assurance: Every commit is validated through:
- 6 different test jobs running in parallel
- Type safety verification
- Code style consistency
- Security vulnerability scanning
- Build verification

Consistent workflow: Enforces development best practices:
- Conventional commit messages
- Semantic versioning
- Comprehensive testing
- Automated documentation

This pipeline transforms package maintenance from a manual, error-prone process into a fully automated workflow.

Key Features and Benefits

Production-Ready Setup

Every generated package includes:
- Modern TypeScript configuration with ES modules
- Comprehensive linting rules with automatic fixes
- Automated testing pipeline with coverage reports
- Professional Git workflow with conventional commits
- Automated release management with semantic versioning

Developer Experience Optimizations

- Fast setup: From idea to coding in under 30 seconds
- Consistent structure: Every package follows the same proven patterns
- Best practices: Modern tooling and configuration
- Zero maintenance: Template updates automatically benefit future packages

Code Quality Standards

The template enforces:
- Type safety with strict TypeScript settings
- Code quality with ESLint and Prettier
- Commit message standards with conventional commits
- Automated testing and coverage requirements
- Proper NPM package metadata and publishing setup

Future Enhancements

Planned Features

- Interactive prompts: Choose between different template variants
- Multiple platforms: Support for GitHub Actions, Azure DevOps
- Framework options: React, Vue, Node.js server templates
- Custom configurations: Allow template customization options

Community Contributions

The template is open source and welcomes:
- New configuration improvements
- Additional tooling integrations
- Bug fixes and optimizations
- Documentation enhancements

Conclusion

Building @sargonpiraev/create-npm-package transformed my NPM package creation workflow from hours to seconds. The key was investing upfront in a solid template that includes all modern tooling and best practices.

This foundation enabled rapid development of subsequent packages and has already saved dozens of hours across multiple projects. The template continues to evolve with the TypeScript ecosystem.

Getting Started

Try the template yourself:

`bash
npx @sargonpiraev/create-npm-package your-project-name
cd your-project-name
npm install
npm run dev
`

Additional Resources

- [Package on NPM](https://www.npmjs.com/package/@sargonpiraev/create-npm-package)
- [Source Code on GitLab](https://gitlab.com/sargonpiraev/create-npm-package)
- [TypeScript Configuration Guide](https://www.typescriptlang.org/tsconfig)
- [Semantic Release Documentation](https://semantic-release.gitbook.io/)
- [Conventional Commits Specification](https://www.conventionalcommits.org/)