create-api-node
v0.1.4
Published
Scaffolding CLI for Node + TypeScript APIs (CAN - Create API Node). Choose Express, NestJS, or VkrunJS template; get a ready-to-run project with ESLint, Prettier, and Jest.
Maintainers
Readme
CAN - Create API Node
· Source
CAN (Create API Node) is a scaffolding CLI published on npm as create-api-node. Use the package name in commands (npx create-api-node); the product name is CAN - Create API Node. For consistency, the repo folder can be named create-api-node to match the package.
It works like Create React App or Vite: it generates a Node + TypeScript API from a chosen template. It sets up the project folder, installs dependencies, and configures ESLint, Prettier, and Jest so you can start coding right away.
Features
- Interactive prompts — Project name and template selection
- Three templates — Express (base), NestJS, or VkrunJS
- Ready-to-run — TypeScript, lint, format, and test configs included in the generated project
- Single command — From zero to a runnable API in one go
Prerequisites
- Node.js >= 18
- npm, yarn, or pnpm (the CLI uses npm by default for the generated project)
Usage
Create a new API project in the current directory. You can pass an optional default project name; the CLI will prompt for confirmation or let you type another name.
# Using npx (recommended)
npx create-api-node
npx create-api-node my-appYou can also use the short name can after installing globally: npm i -g create-api-node, then can or can my-app. With npx use npx create-api-node (the package name).
What happens
- Project name — You're asked for a project name (default:
my-apior the argument you passed). If a folder with that name already exists and is not empty, you'll be prompted to choose another name. - Template — You choose one of the available templates (see below).
- Pipeline — The CLI runs: init (creates/validates folder), generate (copies template and sets package name), install (runs the package manager), lint config (writes ESLint/Prettier), test config (writes Jest), and finalize (prints success and next steps).
- Next steps — You get the exact
cdandnpm run devcommands to start the new project.
Templates
| Template | Description |
|--------|-------------|
| base | Node + Express + TypeScript API with ESLint, Prettier, and Jest. Minimal structure: app.ts, index.ts, routes/health. |
| nest | NestJS API with TypeScript: modules, decorators, CLI. Includes app.module, controller, service, and GET / plus GET /health. |
| vkrun | VkrunJS API with TypeScript. Opinion-free, scalable. Same tooling (ESLint, Prettier, Jest). |
All templates target Node >= 20 and include a health-check route and npm run dev / npm run build / npm start scripts.
Development (CLI repo)
Clone the repo, install dependencies, then use the scripts below. Build the CLI before running it locally.
npm install
npm run build
node dist/bin/index.js
# or
npm start| Script | Description |
|--------|-------------|
| npm run build | Compile TypeScript to dist/ |
| npm run dev | Watch mode (recompile on change) |
| npm start | Run the CLI (node dist/bin/index.js) |
| npm test | Run Jest |
| npm run test:watch | Jest in watch mode |
| npm run test:coverage | Jest with coverage report |
| npm run lint | Run ESLint |
| npm run lint:fix | ESLint with auto-fix |
| npm run format | Prettier on bin/, core/, steps/, utils/ |
Project structure
├── bin/ # CLI entrypoint (prompts, pipeline orchestration)
├── core/ # Context, runner, templates registry
├── steps/ # Pipeline steps: init, generate, install, lint, test, finalize
├── templates/ # Project templates
│ ├── base/ # Express + TypeScript
│ ├── nest/ # NestJS
│ └── vkrun/ # VkrunJS
├── utils/ # Helpers: fs, exec, logger, prompt, spinner, errors
├── package.json
├── tsconfig.json
└── jest.config.cjsArchitecture
The CLI follows a task-based pipeline: the entrypoint collects input via prompts, builds a shared context, then runs a fixed sequence of steps. Each step receives the same context and can fail (aborting the run).
Pipeline order
- Init — Validates or creates the target directory; fails if it already exists and is not empty.
- Generate — Copies the chosen template into the target dir and sets the project name in
package.json. - Install — Runs the package manager (
npm/yarn/pnpm) in the generated project. - Lint config — Writes
.eslintrc.jsonand.prettierrcinto the generated project. - Test config — Writes
jest.config.jsinto the generated project. - Finalize — Prints success and next steps (
cd <dir>,npm run dev).
The runner (orchestration in bin/index.ts) runs these steps in order; no branching, only one path. Conditionals (e.g. which template) live inside steps or the entrypoint.
Dependency rules
- bin/ — Entrypoint only. Imports from
core/,steps/,utils/. No business logic; only prompts, context creation, and step invocation. - core/ — Shared state and registry.
context.tsholdstargetDir,projectName,packageManager,templateBasePath.runner.tsruns a list of steps.templates.tsdefines available templates. Core does not import frombin/orsteps/. - steps/ — Single-responsibility functions
(context) => Promise<void>. Import fromcore/contextandutils/(fs, exec, logger). Do not import frombin/. On error they throw; the entrypoint catches and shows a user-friendly message (viautils/errors). - utils/ — Pure helpers (fs, exec, logger, prompt, spinner, errors). No imports from
core/orsteps/. Reusable and easy to test with mocks. - templates/ — Static files only. No application code; generation logic lives in
steps/generate.ts.
Step contract
Every step exports a function:
(context: Context) => Promise<void>It may read or rely on context fields; it should not depend on Express/HTTP. On failure it throws; the CLI maps errors to user-facing messages (permission denied, install failed, etc.) and exits with code 1.
Principles
- Modular — One step, one job. New steps (e.g. a new config writer) can be added without changing others.
- Pipeline — Single, explicit execution order. No complex control flow in the runner.
- Testable — Steps and utils are unit-tested with mocked
fsandexec; the entrypoint is tested with mocked steps and prompts.
Publishing (maintainers)
npm
Before publishing to npm:
- Run
npm run build(or rely onprepublishOnly, which runs it automatically onnpm publish). - Ensure
package.jsonhas the desiredversionand thatfiles(e.g.dist,templates) are correct. - Run
npm publish(requires an npm account and login withnpm login).
Optional: add repository, homepage, and bugs to package.json so the npm package page shows links to the repo and issue tracker.
GitHub Releases
Releases are published on GitHub Releases. They follow Semantic Versioning and the project rules in .cursor/rules/12-versioning.mdc.
- Tags — Each release is based on a Git tag
vMAJOR.MINOR.PATCH(e.g.v0.1.2). Never skip or reuse version numbers. - Release notes — Notes are derived from CHANGELOG.md. When creating a new release, tag the commit that bumps the version, push the tag, then create the release on GitHub (via the UI or GitHub CLI) with the corresponding changelog section.
- Docs — About GitHub Releases (GitHub Docs).
CI/CD (GitHub Actions)
- CI (
.github/workflows/ci.yml) — Runs on every push and pull request tomainanddevelop: lint, tests, test coverage, and build. - CD (
.github/workflows/release.yml) — Runs when a tagv*is pushed (e.g.v0.1.3): builds and publishes to npm. Uses the release environment so a required reviewer must approve the run before publish. Requires the NPM_TOKEN secret.
Branch protection (main)
On GitHub, main is protected (Settings → Branches) with:
- Require a pull request before merging (no direct pushes).
- Require 1 approval before merging.
- Require status checks to pass — the lint-test-build (CI) job must succeed.
Releases are further protected by the tags-release ruleset (Settings → Rules) and the release environment (Settings → Environments; manual approval before npm publish). For the full, up-to-date configuration (branches, environments, actions, rulesets), see .cursor/rules/14-github-repo-settings.mdc.
Setting up automatic npm publish:
- On npmjs.com, generate an Access Token (Automation or granular with “Publish” scope).
- In the repo: Settings → Secrets and variables → Actions → New repository secret. Name:
NPM_TOKEN, value: the token. - To release: bump
versioninpackage.json, update CHANGELOG.md, commit, then create and push the tag (e.g.git tag v0.1.3 && git push origin v0.1.3). The workflow will publish to npm; you can then create the GitHub Release from the same tag.
License
MIT — see LICENSE.
