Skip to main content

Express.js

Scaffold an Express.js workspace with TypeScript.

You can run this directly from an empty location; scaffold starter base is not a prerequisite. Nova creates the monorepo root and the first Express workspace together.

Why Use This Command?

  1. Installs Express 5 with TypeScript and a tsx watch dev script so you can start writing routes with hot reload on the first command.
  2. Auto-detects monorepo or workspace mode so the same command works whether you're starting fresh or adding to an existing project.
  3. Separates the Express app from process startup, then provides discovery and health routes that are useful immediately and remain easy to test.
  4. Pins TypeScript 6.0.3 and sets rootDir to src so the build emits the build/index.js file used by the start script.
  5. Provides dev, prod, check, build, and clean script groups whose top-level commands delegate to adjacent name:* steps through Nova's script runner.
  6. Can contribute the HTTP service to the repository-wide s6 Docker appliance without changing the Express source template.

Requirements

  • Node.js runtime — Use any Node.js LTS release.
  • Empty directory (monorepo mode) or monorepo root (workspace mode) — The command auto-detects which mode to use.

Usage

Options

FlagDescription
-d, --dry-runRun without writing any files.
--docker-imageAdd the Express service, port 3000, and health check to the s6 image.
--installInstall dependencies after scaffolding; this is the default.
--no-installSkip dependency installation.
--name <name>Project slug when creating a new monorepo; omit at an existing root.
--non-interactiveRequire every answer as a flag and do not open prompts.
--workspace-name <name>Workspace directory name.
--output <dir>Output directory.

Output Structure

text
{project-slug}/
├── package.json
├── nova.config.json
├── apps/
│   └── {workspace-name}/
│       ├── .env
│       ├── .env.sample
│       ├── package.json
│       ├── tsconfig.json
│       └── src/
│           ├── app.ts
│           ├── app.test.ts
│           └── index.ts
└── packages/

With --docker-image, Nova adds root .dockerignore, Dockerfile, and compose.yml entry points plus private assembly files under packages/docker. The Express longrun keeps its HTTP health contract inside the repository's one s6 image.

See Docker Images for the shared runtime and layout contract.

How It Works

Interactive Wizard

When run without flags, Nova collects every answer before it writes files:

Monorepo mode (no package.json found):

  1. Project name — Enter a slug for your monorepo (e.g. my-api).
  2. Workspace name — Enter a slug for the workspace directory (default: express).

The new project is created in ./{project-name} by default and never directly in the current directory.

Workspace mode (package.json with workspaces found):

  1. Workspace name — Enter a slug for the workspace directory (default: express).
  2. Output directory — Confirm the workspace path (default: ./apps/{workspace-name}).

Nova reads the project slug from the root nova.config.json; it does not ask you to rename the project or package.

After collecting the answers, Nova displays the complete plan and asks for one confirmation. It then writes the scaffold and installs dependencies unless you pass --no-install. Project-level generators remain separate commands that you can run after configuring nova.config.json.

Non-Interactive Mode

Agents and automation should add --non-interactive. A new monorepo needs --name, --workspace-name, and --output. An existing monorepo needs only --workspace-name and --output; omit --name because Nova reads the root project slug.

Naming, Registration, and Safety

For project slug my-api and workspace slug api, Nova names the package my-api-app-api. The same name is written to the workspace package.json and its nova.config.json entry. If the root workspaces globs do not include the selected output, Nova adds that exact relative path to the root package.json.

Before writing, Nova requires a readable root package.json and nova.config.json, keeps the output inside the monorepo, rejects duplicate paths and names, and lists any template files it would overwrite. --dry-run performs these checks without changing the project.

Starter API

The generated server exposes / as a compact discovery response and /health as a container-friendly health response. Nova registers PORT in the workspace environment, leaves its local .env value blank, and documents 3000 in .env.sample.

The server uses 3000 when PORT is blank or missing. Any other value must be an integer from 1 through 65535; invalid values and bind failures stop startup instead of printing a false ready message.

The app factory lives in src/app.ts, while src/index.ts owns only runtime startup and the copyable endpoint summary. This keeps route tests offline and makes the app straightforward to import from a larger test suite.

Next Steps

After scaffolding, consider running generators to add project files like .editorconfig, LICENSE, and README.md. The root .gitignore is already generated by the scaffold.