A comprehensive template for AI-driven JavaScript/TypeScript development with full CI/CD pipeline support.
- Multi-runtime support: Works with Node.js, Bun, and Deno
- Universal testing: Uses test-anywhere for cross-runtime tests
- Automated releases: Changesets-based versioning with GitHub Actions
- Code quality: ESLint + Prettier with pre-commit hooks via Husky
- Package manager agnostic: Works with npm, yarn, bun, deno, and pnpm
- Click "Use this template" on GitHub to create a new repository
- Clone your new repository
- Update
package.jsonwith your package name and description - Update the
PACKAGE_NAMEconstant in these scripts:scripts/validate-changeset.mjsscripts/merge-changesets.mjsscripts/publish-to-npm.mjsscripts/format-release-notes.mjsscripts/create-manual-changeset.mjs
- Install dependencies:
npm install - Start developing!
# Install dependencies
npm install
# Run tests
npm test
# Or with other runtimes:
bun test
deno test --allow-read
# Lint code
npm run lint
# Format code
npm run format
# Check all (lint + format + file size)
npm run check.
├── .changeset/ # Changeset configuration
├── .github/workflows/ # GitHub Actions CI/CD
├── .husky/ # Git hooks (pre-commit)
├── examples/ # Usage examples
├── scripts/ # Build and release scripts
├── src/ # Source code
│ ├── index.js # Main entry point
│ └── index.d.ts # TypeScript definitions
├── tests/ # Test files
├── .eslintrc.js # ESLint configuration
├── .prettierrc # Prettier configuration
├── bunfig.toml # Bun configuration
├── deno.json # Deno configuration
└── package.json # Node.js package manifest
This template is designed to work seamlessly with all major JavaScript runtimes:
- Node.js: Primary runtime, uses built-in test runner (
node --test) - Bun: Fast alternative runtime with native test support (
bun test) - Deno: Secure runtime with built-in TypeScript support (
deno test)
The test-anywhere framework provides a unified testing API that works identically across all runtimes.
While package.json is the source of truth for dependencies, the template supports:
- npm: Default, generates
package-lock.json - yarn: Uses
yarn.lock - bun: Uses
bun.lockb - pnpm: Uses
pnpm-lock.yaml - deno: Uses
deno.jsonfor configuration
Note: package-lock.json is not committed by default to allow any package manager.
- ESLint: Configured with recommended rules + Prettier integration
- Prettier: Consistent code formatting
- Husky + lint-staged: Pre-commit hooks ensure code quality
- File size limit: Scripts must stay under 1000 lines for maintainability
The release workflow uses Changesets for version management:
- Creating a changeset: Run
npm run changesetto document changes - PR validation: CI checks for valid changeset in each PR
- Automated versioning: Merging to
maintriggers version bump - npm publishing: Automated via OIDC trusted publishing (no tokens needed)
- GitHub releases: Auto-created with formatted release notes
Two manual release modes are available via GitHub Actions:
- Instant release: Immediately bump version and publish
- Changeset PR: Create a PR with changeset for review
The GitHub Actions workflow (.github/workflows/release.yml) provides:
- Changeset check: Validates PR has exactly one changeset (added by that PR)
- Lint & format: Ensures code quality standards
- Test matrix: 3 runtimes × 3 OS = 9 test combinations
- Changeset merge: Combines multiple pending changesets at release time
- Release: Automated versioning and npm publishing
The CI/CD pipeline is designed to handle concurrent PRs gracefully:
-
PR Validation: Only validates changesets added by the current PR, not pre-existing ones from other merged PRs. This prevents false failures when multiple PRs merge before a release cycle completes.
-
Release-time Merging: If multiple changesets exist when releasing, they are automatically merged into a single changeset with:
- The highest version bump type (major > minor > patch)
- All descriptions preserved in chronological order
This design decouples PR validation from the need to pull changes from the default branch, reducing conflicts and ensuring that even if CI/CD fails, all unpublished changesets will still get published when the error is resolved.
After creating a repository from this template, update the package name in:
package.json:"name": "your-package-name".changeset/config.json: Package references- Scripts that reference the package name (see Quick Start)
Customize ESLint in eslint.config.js. Current configuration:
- ES Modules support
- Prettier integration
- No console restrictions (common in CLI tools)
- Strict equality enforcement
- Async/await best practices
- Strict unused variables rule: No exceptions - all unused variables, arguments, and caught errors must be removed (no
_prefix exceptions)
Configured in .prettierrc:
- Single quotes
- Semicolons
- 2-space indentation
- 80-character line width
- ES5 trailing commas
- LF line endings
| Script | Description |
|---|---|
npm test |
Run tests with Node.js |
npm run lint |
Check code with ESLint |
npm run lint:fix |
Fix ESLint issues automatically |
npm run format |
Format code with Prettier |
npm run format:check |
Check formatting without changing files |
npm run check |
Run all checks (lint + format) |
npm run changeset |
Create a new changeset |
- Fork the repository
- Create a feature branch:
git checkout -b feature/my-feature - Make your changes
- Create a changeset:
npm run changeset - Commit your changes (pre-commit hooks will run automatically)
- Push and create a Pull Request
Unlicense - Public Domain