node-deploy
The node-deploy skill automates the building and deployment of Node.js, JavaScript, and TypeScript applications by detecting project configuration, selecting appropriate package managers and runtime versions, and generating deployment commands. Use this skill when deploying any Node.js project, particularly those with complex monorepo structures, multiple framework types, or custom build requirements where automated version and dependency management is needed.
git clone --depth 1 https://github.com/nixopus/nixopus /tmp/node-deploy && cp -r /tmp/node-deploy/api/skills/node-deploy ~/.claude/skills/node-deploySKILL.md
# Node.js Deployment
## Detection
Project is Node.js if `package.json` exists in the root directory.
## Versions
Node.js version priority:
1. `.node-version` or `.nvmrc` file
2. `engines.node` field in `package.json`
3. `mise.toml` or `.tool-versions`
4. Defaults to **22**
### Bun
If Bun is detected as the package manager:
1. `engines.bun` field in `package.json`
2. `.bun-version` file
3. `mise.toml` or `.tool-versions`
4. Defaults to **latest**
When Bun is the primary runtime, Node.js must still be installed if:
- The project uses Corepack (`packageManager` field exists in `package.json`)
- Build tools require Node (Astro, Vite, or native addon compilation via `node-gyp`)
- Any `package.json` script explicitly invokes `node`
## Package Managers
Detect in order:
1. **`packageManager` field** in `package.json` → use Corepack to install exact version (e.g. `pnpm@9.1.0`)
2. **Lock files:**
| Lock file | Package manager |
|---|---|
| `package-lock.json` | npm |
| `yarn.lock` | Yarn (check `.yarnrc.yml` to distinguish Yarn Berry from Classic) |
| `pnpm-lock.yaml` | pnpm |
| `bun.lockb` or `bun.lock` | Bun |
3. **`engines` field** — `engines.pnpm` → pnpm, `engines.bun` → Bun, `engines.yarn` → Yarn
4. **Default:** npm
### Install Commands
| Package manager | With lockfile | Without lockfile |
|---|---|---|
| npm | `npm ci` | `npm install` |
| yarn (classic) | `yarn install --frozen-lockfile` | `yarn install` |
| yarn (berry) | `yarn install --immutable` | `yarn install` |
| pnpm | `pnpm install --frozen-lockfile` | `pnpm install` |
| bun | `bun install --frozen-lockfile` | `bun install` |
## Runtime Variables
Set `NODE_ENV=production` for the runtime stage. During the build, keep `NPM_CONFIG_PRODUCTION=false` and `YARN_PRODUCTION=false` so dev dependencies remain available for compilation. Disable update notifications with `NPM_CONFIG_UPDATE_NOTIFIER=false` and `NPM_CONFIG_FUND=false`. Set `CI=true` to enable CI-appropriate behavior in tooling.
## Build & Start
### Start Command Resolution
1. `start` script in `package.json`
2. `main` or `module` field in `package.json` (run with `node`)
3. `server.js`, `index.js`, or `index.ts` in root (run with `node`)
### Build Command Resolution
1. `build` script in `package.json` → `${packageManager} run build`
2. If no build script → skip build step
### Output Directory
| Framework | Output directory |
|---|---|
| NestJS | `dist` |
| Next.js (SSR) | `.next` |
| Next.js (export) | `out` |
| Nuxt | `.output` |
| SvelteKit | `build` |
| Remix | `build` |
| Astro | `dist` |
| Vite | `dist` |
| Angular | `dist/${projectName}` |
| React (CRA) | `build` |
| React Router | `build/client` |
| Default | `dist` |
## Port Detection
1. **Environment files** — `PORT=<number>` from `.env`, `.env.example`, `.env.production`
2. **`package.json` scripts** — scan `start`, `dev`, `serve` for `-p <port>`, `--port <port>`, `PORT=<port>`
3. **Framework config** — `next.config.*` or `vite.config.*` for `port: <number>`
4. **Framework defaults:**
| Framework | Default port |
|---|---|
| Express | 3000 |
| Fastify | 3000 |
| NestJS | 3000 |
| Hono | 3000 |
| Next.js | 3000 |
| Nuxt | 3000 |
| Remix | 3000 |
| SvelteKit | 5173 |
| Astro | 4321 |
| Vite | 5173 |
| React | 3000 |
| Vue | 8080 |
5. **Final default:** 3000
## Framework Detection
From `package.json` dependencies (merge `dependencies` + `devDependencies`). First match wins.
| Package pattern | Framework | Category |
|---|---|---|
| `express` | Express | Backend |
| `fastify` | Fastify | Backend |
| `@nestjs/core` | NestJS | Backend |
| `hono` | Hono | Backend |
| `next` | Next.js | FullStack |
| `nuxt` | Nuxt | FullStack |
| `@sveltejs/kit` | SvelteKit | FullStack |
| `@remix-run/node` or `@remix-run/react` | Remix | FullStack |
| `astro` | Astro | Static |
| `vite` (without a higher framework) | Vite | Frontend |
| `react` + `react-dom` (without Next/Remix) | React | Frontend |
| `vue` (without Nuxt) | Vue | Frontend |
Config file fallback:
| Config file | Framework |
|---|---|
| `nest-cli.json` | NestJS |
| `next.config.js`, `next.config.mjs`, `next.config.ts` | Next.js |
| `nuxt.config.js`, `nuxt.config.ts` | Nuxt |
| `svelte.config.js` | SvelteKit |
| `remix.config.js` | Remix |
| `astro.config.mjs`, `astro.config.js` | Astro |
| `vite.config.ts`, `vite.config.js` | Vite |
| `vue.config.js` | Vue |
| `angular.json` | Angular |
### Framework-Specific Behavior
**Next.js**
- Check `next.config.*` for `output: "standalone"` → standalone build (smaller image, includes `node_modules` subset)
- `output: "export"` → static site, no server needed
- Cache `.next/cache` between builds
- `app/` directory → React Server Components
**Nuxt**
- Default start: `node .output/server/index.mjs`
- Cache `node_modules/.cache`
**Astro**
- If `output` is not `"server"` → static site
- Cache `node_modules/.astro`
## Monorepo Support
### Detection Signals
- `workspaces` field in root `package.json`
- `pnpm-workspace.yaml`
- Build orchestrators: `turbo.json`, `nx.json`, `lerna.json`, `rush.json`
- Conventional directories: `apps/`, `packages/`, `services/`
### Workspace Package Resolution
- **pnpm:** Parse `pnpm-workspace.yaml` → `packages:` list
- **npm / yarn / bun:** Parse `workspaces` field in root `package.json`
### Build Steps
1. Detect workspace configurations automatically
2. Install all workspace dependencies (copy all `package.json` files + root lock file)
3. Respect workspace dependency links
4. Cache workspace `node_modules`
5. Build the target workspace package
## Optimizing the Install Layer
**Always copy:**
- `package.json` (root + workspace packages if monorepo)
- Lock file
- `pnpm-workspace.yaml` (if pnpm monorepo)
- `.npmrc` (if exists — contains registry config)
**Framework-specific install files** (copy if they exist, they trigger postinstall):
- `prisma/schema.prisma` — Prisma generates client on `postinstall`
- `.env` files needed at build time (e.g. Next.js `NEXT_PUBLIC_*Reference for all Nixopus API operations callable via nixopus_api(method, path, body)
Generate Caddyfile configurations for static sites and reverse proxies — SPA fallback routing, cache headers, compression, redirects, and error pages. Use when deploying a static site that needs custom Caddy configuration, or when the user needs SPA routing, caching, or redirect rules.
Generate docker-compose.yml for multi-service setups including databases, caches, and service dependencies. Use when the app needs a database, cache, message broker, or has multiple independently deployable services.
Size container memory and CPU limits, diagnose OOM kills and CPU throttling, and recommend resource adjustments by ecosystem. Use when containers are being OOM-killed, running slowly, or when setting initial resource limits for a deployment.
Build and deploy C/C++ applications — CMake, Meson, Ninja, and Dockerfile patterns. Use when deploying a C or C++ project, or when CMakeLists.txt or meson.build is detected.
Run database migrations safely during deployment — framework-specific commands, pre-deploy vs post-deploy timing, health gates, and rollback strategies. Use when the app has a database migration system and needs migrations run during deployment.
Build and deploy Deno applications — version detection, dependency caching, and Dockerfile patterns. Use when deploying a Deno project, or when deno.json or deno.jsonc is detected.
Sub-agent routing table — which agent handles diagnostics, machine health, infrastructure, GitHub, billing, and notifications. Load when the current task is not a direct deployment.