nod-cli
v0.4.8
Published
Backend scaffolding CLI for Express, Hono, and more - with best practices built-in
Downloads
671
Maintainers
Readme
nod-cli
Backend scaffolding CLI for Node.js with best practices built-in. Generate production-ready Express or Hono projects with TypeScript, authentication, database connections, AI features, and more.
Installation
corepack prepare [email protected] --activate
pnpm add -g nod-cliQuick Start
# Create a new project (interactive)
nod init my-api
# Or use shorthand
nod my-api
# Non-interactive default: strict production API (TypeScript by default)
nod init my-api --yes
# One-command AWS SAM backend
nod backend my-api
# Strict SAM backend with shared Postgres rate limits
nod init my-api --preset aws-sam-backend --rate-limit-store postgres --yes
# Or pick a specific preset
nod init my-api --preset 1 --framework express --yes
# Non-interactive with JavaScript
nod init my-api --preset api --no-ts --yes
# Follow the interactive prompts to configure:
# - Preset (production-api, aws-sam-backend, minimal, api, full, ai, 1, or custom presets)
# - Framework (Express/Hono)
# - TypeScript/JavaScript
# - Database (PostgreSQL/MySQL/Supabase/None)
# - ORM (Drizzle/Raw SQL)
# - Authentication (JWT/JWKS/Supabase/Better Auth/None)
# - AI features (RAG, Chat, Langfuse)
# - Deployment (AWS SAM, Vercel cron, GitHub workflow)
# - Rate limit store (Postgres, Redis, None)
# - Docker & PM2 configurationPresets
| Preset | Description |
| --------- | ----------------------------------------------------------------------- |
| production-api | Default strict API: Supabase, Drizzle, Better Auth, Postgres-backed rate limits, trusted origins, Lambda/SAM |
| aws-sam-backend | Production AWS SAM backend: Express, TypeScript, Supabase/Drizzle, Better Auth, static Drizzle rate limits, strict security, pnpm dependency layer, Node 22 Lambda |
| minimal | Basic setup, no database or auth |
| api | Standard REST API with JWT auth |
| full | All features including Supabase, Drizzle, Vercel cron |
| ai | Full preset + RAG, Chat, Langfuse |
| 1 | Supabase + Drizzle + API Audit + GitHub Actions |
| custom | Choose your own features |
Custom Presets
Create and manage your own presets:
# List all presets
nod preset list
# Create a custom preset
nod preset create mystack
# Set default preset
nod preset default mystack
# Show preset details
nod preset show mystack
# Delete a custom preset
nod preset delete mystackCustom presets are stored in ~/.nod-cli/presets.json and can be used like built-in presets:
nod init my-api --preset mystack --yesCommands
Initialize Project
nod init <project-name>
# or shorthand
nod <project-name>Create AWS SAM Backend
nod backend <project-name>This is shorthand for a production AWS SAM backend preset with Express, TypeScript, strict security, Supabase/Drizzle, Better Auth, Postgres-backed rate limits, a pnpm-built dependency layer, Node.js 22 Lambda, template.yaml, samconfig.toml, and docs/aws-sam-setup.md.
Options
| Option | Description | Default |
| ------------------------- | ---------------------------------------------- | --------- |
| --framework <framework> | Web framework: express or hono | express |
| --ts | Use TypeScript | true |
| --no-ts | Use JavaScript instead of TypeScript | - |
| --db <database> | Database: pg, mysql, supabase, or none | pg |
| --auth <auth> | Auth: jwt, jwks, supabase, cookie-session, better-auth, or none | preset |
| --queue <queue> | Queue: bull or none | none |
| --preset <preset> | Use a preset configuration | production-api in non-interactive mode |
| --security <mode> | Security: basic or strict | preset |
| --deploy-target <target>| Deploy target: node or lambda-sam | preset |
| --cron <boolean> | Include node/Lambda cron support | preset |
| --vercel-cron <boolean> | Include Vercel cron config | preset |
| --rate-limit-store <store> | Rate limit store: postgres, redis, or none | postgres for strict Drizzle/SAM |
| -y, --yes | Skip prompts, use defaults | - |
Examples
# Interactive mode
nod init my-api
# TypeScript with preset 1 (non-interactive)
nod my-api --preset 1 --yes
# JavaScript project with API preset
nod init my-api --preset api --no-ts --yes
# Hono framework with Supabase
nod init my-api --framework hono --db supabase --auth supabase --yes
# Minimal JavaScript project
nod my-api --preset minimal --no-ts --yesAdd Components
Navigate to your project directory first:
cd my-apiThen add components:
# Add route with controller and service
nod add route users
# Add complete auth module
nod add auth
# Add shared-store rate limiter (Postgres preferred)
nod add middleware --name rateLimit --type rateLimit --rate-limit-store postgres --yes
# Add Redis-backed rate limiter
nod add middleware --name rateLimit --type rateLimit --rate-limit-store redis --yes
# Add CORS middleware and apply globally
nod add cors
# Add service
nod add service email
# Add cron job support
nod add cron
# Add PM2 configuration
nod add pm2
# Add Vercel cron setup
nod add vercel-cron
# Add GitHub Actions workflow for Vercel deployment
nod add github-actions
# Add RAG service
nod add rag
# Add Chat service
nod add chat
# Add Supabase helper
nod add supabase
# Add Drizzle ORM
nod add drizzle
# Add Langfuse
nod add langfuseTransform Existing Project
Add nod features to an existing project:
nod transformSelect features to add:
- Environment Config (staging/production)
- Supabase Helper
- Drizzle ORM Setup
- Supabase JWT Auth Middleware
- Vercel Cron Setup
- GitHub Workflow
- RAG Service
- Chat Service
- Langfuse Integration
- Error Handler
- Winston Logger
- Response Formatter
Manage Presets
nod preset list # List all presets
nod preset create [name] # Create a new preset
nod preset delete [name] # Delete a custom preset
nod preset default [name] # Set default preset
nod preset show <name> # Show preset detailsValidate Project
nod validateRun MCP Server
Run a built-in local MCP server over stdio:
nod mcpThis exposes MCP tools:
nod_help- quick command usage examplesnod_run- executenodcommands locally (init/add/transform/validate/preset)
Example Claude Desktop configuration:
{
"mcpServers": {
"nod-cli": {
"command": "nod",
"args": ["mcp"]
}
}
}Project Structure
Generated projects follow this structure:
my-api/
├── src/
│ ├── routes/ # Route definitions
│ ├── controllers/ # Request handlers
│ ├── services/ # Domain services (e.g. user.service.ts)
│ ├── middleware/ # Custom middleware
│ ├── auth/ # Auth services (nod add auth)
│ ├── config/ # App configuration
│ ├── helpers/ # Reusable helpers (e.g. user.helper.ts)
│ ├── utils/ # Utility modules (logger, etc.)
│ ├── db/ # Database connection & schema
│ ├── environments/ # Staging/production configs
│ ├── cron/ # Cron jobs
│ └── types/ # TypeScript types (TS only)
├── docs/ # Project documentation & plans
│ └── README.md # Documentation index
├── temp/ # Temporary output files (git-ignored)
├── sql/ # SQL schema files
├── .github/ # GitHub workflows
├── .env.example # Environment variables template
├── .gitignore
├── package.json
├── tsconfig.json # TypeScript config (TS only)
├── tsconfig.build.json # TypeScript emit config for non-SAM TS projects
├── tsconfig.lambda.json # TypeScript emit config for SAM TS projects
├── scripts/ # SAM build and runtime import checks (AWS SAM backend)
├── drizzle.config.ts # Drizzle config (if using Drizzle)
├── template.yaml # AWS SAM template (if using AWS SAM)
├── samconfig.toml # AWS SAM deploy profiles (if using AWS SAM)
├── vercel.json # Vercel config (if using Vercel cron)
├── Dockerfile # Docker config (if enabled)
├── docker-compose.yml # Docker Compose (if enabled)
├── ecosystem.config.js # PM2 config (if enabled)
└── README.md # Project READMESpecial Folders
| Folder | Purpose |
| ------- | ------------------------------------------------------------------------------------------------- |
| docs/ | Project documentation, architecture decisions, API docs, and development plans. Committed to git. |
| temp/ | Temporary output files (PDFs, exports, generated files). Git-ignored. |
Configuration Options
| Option | Choices | Description |
| --------------- | --------------------------------- | ------------------------------------------ |
| Framework | Express, Hono | Web framework |
| TypeScript | Yes, No | Type safety (use --no-ts for JavaScript) |
| Database | PostgreSQL, MySQL, Supabase, None | Database driver |
| ORM | Drizzle, Raw SQL, None | ORM choice |
| Auth | JWT, JWKS, Supabase, None | Authentication method |
| Cron | Yes, No | Scheduled jobs support |
| Environments | Yes, No | Staging/production config |
| RAG | Yes, No | Vector search & retrieval |
| Chat | Yes, No | Conversation management |
| Langfuse | Yes, No | LLM observability |
| Vercel Cron | Yes, No | Vercel cron configuration |
| Rate Limit Store| Postgres, Redis, None | Shared rate-limit storage |
| GitHub Workflow | Yes, No | CI/CD workflow |
| Docker | Yes, No | Container configuration |
| PM2 | Yes, No | Process manager config |
Features
Core
- Declarative Routes - Clean, configuration-based route definitions
- Type Safety - Full TypeScript support (or plain JavaScript with
--no-ts) - PM2 Cluster Mode - Thread-safe cron jobs with distributed locking
- Shared Rate Limits - Postgres/Drizzle by default, Redis when selected
- Docker Ready - Dockerfile and docker-compose included
- Zod Validation - Runtime config validation (TypeScript only)
- Documentation Folder - Built-in
docs/folder for project documentation - Temp Output Folder - Git-ignored
temp/folder for generated files
Database
- Supabase Integration - Full Supabase client with storage helpers
- Drizzle ORM - Type-safe ORM with connection pooler support
- Environment Config - Separate staging/production configurations
Authentication
- Complete Auth Module -
nod add authgenerates JWKS, JWT, password hashing, Google OAuth, forgot password, email service - Supabase JWT Auth - JWKS-based JWT verification using jose library
- Custom JWT - Roll your own tokens with auto-generated RSA keys
- Password Hashing - Bcrypt-based password hashing with strength validation
- Google OAuth - Server-side token verification
- Permission Middleware - Role-based access control from JWT payload
AI Features
- RAG Service - Vector similarity search with OpenAI embeddings
- Chat Service - Conversation management with LangChain
- Langfuse - Optional LLM observability and tracing
Deployment
- AWS SAM - Lambda/API Gateway backend with TypeScript ESM
.jsemit and a pnpm-built dependency layer - Vercel Cron - Cron job configuration with auth middleware
- GitHub Workflow - Deploy trigger workflow
AWS SAM Backend Pattern
Generated SAM backends use ESM .js files under "type": "module". They do not emit .mjs.
The Lambda build is deliberately split:
dist/contains TypeScript-emitted application code and Lambda handlers.dist-layer/contains productionnode_modulesinstalled with pnpm.template.yamlattaches the dependency layer to every function and usesBuildMethod: makefile.scripts/check-sam-runtime-imports.jsimports every built handler aftersam build --parallel.
This avoids standalone bundler failures from hidden dynamic imports such as packages that compute import('drizzle-orm') at runtime. Postgres rate limits use generated static Drizzle SQL instead of rate-limiter-flexible's Drizzle adapter. Redis rate limits still use rate-limiter-flexible.
Generated Drizzle clients are Lambda-safe by default: prepare: false, DATABASE_POOL_MAX=2, DATABASE_CONNECT_TIMEOUT_SECONDS=5, DATABASE_IDLE_TIMEOUT_SECONDS=20, and DATABASE_MAX_LIFETIME_SECONDS=1800. Use an RDS Proxy or database pooler URL for Lambda.
Generated API audit middleware skips GET, HEAD, and OPTIONS DB writes. Use ALB/API Gateway/WAF/access logs for read-path traffic and keep DB audit rows for mutations or explicit domain events.
Running Your Project
cd my-api
pnpm install
cp .env.example .env
# Edit .env with your settings
pnpm devAvailable Scripts
| Script | Description |
| ---------------- | ---------------------------------------- |
| pnpm dev | Start development server with hot reload |
| pnpm build | Build for production (TypeScript only) |
| pnpm start | Start production server |
| pnpm lint | Lint code with ESLint |
| pnpm format | Format code with Prettier |
| pnpm test | Run tests (if testing enabled) |
Production
pnpm build
pm2 start ecosystem.config.jsPM2 Commands
pnpm start:pm2 # Start with PM2
pnpm stop:pm2 # Stop PM2 processes
pnpm restart:pm2 # Restart PM2 processes
pnpm logs:pm2 # View PM2 logs
pnpm monit:pm2 # Monitor PM2 processesDrizzle Commands
pnpm db:generate # Generate migrations
pnpm db:migrate # Apply migrations
pnpm exec drizzle-kit migrate --config=<drizzle.config.ts|drizzle.config.js> # Apply migrations
pnpm db:studio # Open Drizzle StudioCI/CD & Non-Interactive Mode
For CI/CD pipelines, use the --yes flag to skip all prompts:
# In CI environment
nod init my-api --preset api --yes
# With specific options
nod init my-api --preset 1 --framework express --no-ts --yesThe CLI also respects the CI environment variable - when CI=true, it automatically uses non-interactive mode.
License
MIT
