npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

create-express-new

v1.4.0

Published

Express 5 application generator: ESM, TypeScript and CommonJS app templates. A modern successor to express-generator.

Readme

create-express-new

An application generator for Express 5, creating web apps or JSON APIs as ES modules, TypeScript or CommonJS that run on current Node.js with no build step.

NPM Version NPM Downloads Node.js Version License CI OpenSSF Scorecard

create-express-new is a fork of express-generator, the original Express application generator, reimagined for today's Express apps. It keeps the familiar express command and project layout, and updates everything it generates for Express 5 and modern Node.js. It is not affiliated with or endorsed by the Express project.

Quick Start

Run the generator with no arguments to be guided through the options (requires Node.js 22.9 or newer):

$ pnpm create express-new@latest

npm create express-new@latest starts the same wizard. It asks for:

  • the project directory (. for the current directory)
  • a web app, a JSON API or a web app with a JSON API, and the view engine
  • the language: JavaScript, TypeScript or CommonJS
  • optional middleware, and CSRF protection with sessions
  • the request logger
  • extras: a Dockerfile, ESLint and Sass
  • a .gitignore
  • the package manager the app requires: pnpm, or npm

Esc (or ←) goes back a question, keeping your answers. At the end the wizard shows the equivalent command, to repeat the setup or use in scripts, and offers to install the dependencies.

In a directory that already has files:

  • Files the app would replace are listed, and the wizard asks whether to overwrite them, keep your config files (see --keep-config below) or cancel.
  • Files with the same contents are left alone.
  • An existing .gitignore is never replaced; the lines it is missing are added at the end.
  • A file where the app needs a folder, or a folder where it needs a file, stops anything being written.
  • Files from an earlier app with other options, such as an app.js next to a new app.ts, are left in place and listed in a warning.

Or pass the directory and options directly:

$ pnpm create express-new@latest my-app --ts --helmet
$ cd my-app
$ pnpm install

With npm create, put the options after --: npm create express-new@latest my-app -- --ts --helmet. npx create-express-new my-app --ts --helmet needs no --. Either way the app requires pnpm unless you add --pm=npm. Add --install to install the dependencies too, with the app's package manager.

Start it at http://localhost:3000/, and run its tests, written with the built-in node:test runner:

$ pnpm dev      # restarts on change
$ pnpm start    # without restarting
$ pnpm test

An app generated with --pm=npm uses npm install, npm run dev, npm start and npm test.

You can also install the generator globally, which provides the express command:

$ npm install -g create-express-new
$ express --view=ejs --helmet my-app

The original express-generator provides an express command too, so install only one of them globally.

What You Get

my-app
├── .env.example      # example environment variables; copy to .env
├── .gitignore        # ignores node_modules, .env files, logs and coverage
├── app.js            # the Express app: middleware, views, routes, error handling
├── bin/www.js        # starts the server, with graceful shutdown on SIGINT/SIGTERM
├── package.json      # "type": "module", start/dev/test scripts
├── public/           # static files, including stylesheets/style.css
├── routes/           # index.js and users.js routers
├── test/app.test.js  # node:test tests for the app
└── views/            # error, index, layout and users templates (pug by default)

Every app has a GET /health endpoint that responds with { "status": "ok" }, for load balancers, container health checks and uptime monitors. It is defined before the middleware, so it stays fast and out of the request logs.

Server errors (5xx) are logged with console.error; client errors (4xx), such as a 404, are not. Errors render with the error view, or as plain text with --no-view. Client errors show their message. Server errors only say Internal Server Error outside development, so internal details are never sent; development shows every error's message and stack.

JSON APIs

--api generates a JSON API instead of a web app: no views, static files or form parsing, and routes that respond with JSON.

my-api
├── app.js            # JSON body parsing, routes, JSON 404 and error handling
├── bin/www.js
├── package.json
├── routes/           # index.js and users.js, responding with JSON
└── test/app.test.js

Errors are always JSON, such as { "error": "Not Found" }, and follow the same rules as web apps: client errors include their message, server errors only say Internal Server Error in production, and development adds the stack trace. Express runs in development mode unless NODE_ENV is set, so set NODE_ENV=production when you deploy.

--api works with --cjs, --ts and the optional middleware, except --session.

Web apps with a JSON API

--api with a view engine, such as --api --view=pug, generates a web app that has a JSON API too: everything a web app has, and a routes/api folder of routers mounted at /api, apart from the routers of the pages.

my-app
├── app.js            # the web app, with JSON errors under /api
├── routes/
│   ├── api/
│   │   ├── index.js  # JSON routes: GET /api, and the routers of the API's resources
│   │   └── users.js  # GET /api/users
│   ├── index.js      # the home page
│   └── users.js      # the users pages
├── views/
└── ...

To add a resource to the API, add its router to routes/api and mount it in routes/api/index.js.

Every error of a request under /api is JSON, in the same shape as a JSON API's: the 404 of an unknown route, an error a route throws, and the errors of the middleware before the routes, such as a request body that is not valid JSON. Every other error renders the error view.

With --cors and --csrf, you choose which routes they apply to:

  • --cors-scope=api (default) lets other origins call the API only, not read the pages; --cors-scope=all lets them call the whole app.
  • --csrf-scope=all (default) requires the CSRF token under /api too, for an API your own pages call; --csrf-scope=pages leaves the API out, for an API other clients call without the session cookie.

The wizard asks both.

The view engine has to be given, as --api alone is a JSON API without views: use --view=pug for the default one. --api does not add an API to a --no-view app.

Module formats

  • ES modules (default): import/export, import.meta.dirname and node: built-ins.
  • CommonJS (--cjs): the same app with require()/module.exports.
  • TypeScript (--ts): .ts files that Node.js 22.18+ runs directly by stripping types, so there is no build step. Includes a strict tsconfig.json, the @types packages the app needs and a typecheck script that runs tsc. --ts cannot be combined with --cjs.

Configuration

The start and dev scripts load environment variables from a .env file when one exists, using Node.js's built-in --env-file-if-exists, so no dotenv package is needed. Start from the generated example:

$ cp .env.example .env

Variables already set in the environment take precedence over .env, so your hosting platform's settings always win. The dev script restarts when .env changes. The generated .gitignore keeps .env, and every other .env.* file except .env.example, out of version control.

Optional middleware

By default, generated apps include only request logging, body parsing and static files (no static files with --api). Add more with:

  • --helmet: helmet security headers
  • --compression: gzip/brotli response compression
  • --cookies: cookie-parser, for reading req.cookies
  • --cors: cors, allowing requests from other origins
  • --rate-limit: express-rate-limit, limiting each client to 100 requests every 15 minutes
  • --session (not for JSON APIs without views): express-session, for req.session
  • --csrf (with --session and a view engine): csrf-sync CSRF protection for forms
  • --uploads: multer and a POST /uploads route that takes one file of up to 5 MB

Optional middleware covers each one's settings and environment variables, sending the CSRF token from forms and JavaScript, running behind a proxy, and how uploaded files are stored and checked.

Request logging

Requests are logged with morgan by default, one readable line per request. --logger=pino uses pino-http instead, which logs JSON for log collectors and adds req.log for your own logs. The dev script pipes them through pino-pretty to keep them readable. Either way, requests are not logged while the tests run.

Package manager

Every app requires one package manager, pnpm by default or npm with --pm=npm, so other package managers refuse to install the app or run its scripts. It also has settings that protect installs from compromised packages: new releases wait 3 days before they are installed, and the install scripts of dependencies are not run. An npm app needs npm 12 or newer, which does not come with Node.js 22 or 24.

Package manager compares the pnpm and npm settings, and covers allowing a dependency's install script, installing a release sooner and changing package manager later.

Docker

--docker adds a Dockerfile and .dockerignore for a production image. Install dependencies first, as the image installs from the lockfile:

$ pnpm install
$ docker build -t my-app .
$ docker run -p 3000:3000 my-app

The image:

  • is based on node:22-slim, the latest release of the minimum supported Node.js version
  • installs only production dependencies, in a build stage of their own, so the package manager is not in the final image
  • with --sass, compiles the stylesheets in another build stage, so Sass is not in the final image
  • runs the app as the unprivileged node user with NODE_ENV=production
  • checks /health with a HEALTHCHECK
  • runs node directly, so it receives SIGTERM and shuts down gracefully
  • does not copy .env files; set environment variables with your container platform instead. With --session, the app needs SESSION_SECRET to start, such as docker run -e SESSION_SECRET=... -p 3000:3000 my-app

Linting

--lint adds ESLint with its recommended rules and a lint script. With --ts it also adds typescript-eslint; as typescript-eslint does not support TypeScript 7 yet, these apps use TypeScript 6.

Sass

--sass adds Sass to a web app: a public/stylesheets/style.scss in place of style.css, compiled to the CSS the app serves.

$ pnpm start        # compiles the stylesheets, then starts the app
$ pnpm dev          # compiles them once, then restarts the app on change
$ pnpm css:watch    # recompiles them on change, in a second terminal

Sass is a development dependency, so pnpm start fails where only production dependencies are installed: compile the stylesheets first with pnpm css, as the --docker image does. Using Sass covers this, the files it ignores and adding Sass to an existing app.

Command Line Options

-v, --view <engine>  add view <engine> support (ejs|hbs|pug|twig) (defaults to pug)
    --no-view        use static html instead of view engine
    --api            generate a JSON API, without views or static files
                     (with --view, a web app with a JSON API at /api)
    --cjs            generate CommonJS modules instead of ES modules
    --ts             generate TypeScript, run directly by Node.js
    --helmet         add helmet middleware for security headers
    --compression    add compression middleware for gzip/brotli responses
    --cookies        add cookie-parser middleware
    --cors           add cors middleware for cross-origin requests
    --cors-scope <scope>
                     with --api and --view, the routes other origins can
                     call (api|all) (defaults to api)
    --rate-limit     add express-rate-limit to limit requests per client
    --session        add express-session for sessions (not with --api alone)
    --csrf           add CSRF protection for forms (needs --session)
    --csrf-scope <scope>
                     with --api and --view, the routes that need a CSRF
                     token (all|pages) (defaults to all)
    --uploads        add multer and an upload route at /uploads
    --logger <name>  request logger (morgan|pino) (defaults to morgan)
    --sass           add Sass, compiling .scss stylesheets (not with --api alone)
    --docker         add a Dockerfile for a production image
    --lint           add ESLint and a lint script
    --pm <name>      package manager the app requires (pnpm|npm) (defaults to pnpm)
    --install        install the dependencies after creating the app
    --no-git         skip the .gitignore
-f, --force          force on non-empty directory
    --keep-config    keep existing config files (.env.example, Dockerfile,
                     .dockerignore, tsconfig.json, eslint.config.*,
                     pnpm-workspace.yaml, .npmrc)
    --version        output the version number
-h, --help           output usage information

Changes From express-generator

This fork started from express-generator 4.16.1. It generates Express 5 apps as ES modules, with pug in place of jade, for Node.js 22.9 or newer. --view=<engine> replaces the --ejs, --hbs and --pug aliases, and apps use plain CSS unless you add Sass with --sass; the other CSS preprocessors are gone.

Contributing

$ pnpm install
$ pnpm test      # generates, installs and runs apps for each option
$ pnpm lint

This repository requires pnpm 11 or newer, as generated apps do by default, so install pnpm first; npm refuses to install it or run its scripts. The tests that install an npm app are skipped unless your npm is version 12 or newer.

See Maintaining for keeping the dependency versions of generated apps current, and for releasing.

License

MIT. Originally created by TJ Holowaychuk and the Express contributors.