Browse documentation
DocumentationGetting started
CLI & GETTING STARTED v0.1.0

Build with clarity.

A lightweight modular backend engine and CLI toolkit for Express + TypeScript.

ExetJS gives your backend a clear starting point: a small runtime, explicit modules, typed configuration, and a CLI that handles the repetitive work. Express remains visible, so the application stays yours.

ExpressTypeScriptES ModulesMIT license
Structure you can see.

No decorators, reflection metadata, heavy dependency injection container, or automatic module discovery. Modules are registered explicitly.

Installation #

You need Node.js 24 LTS or newer and a package manager. Install the CLI globally using pnpm or npm.

pnpm
pnpm add -g @exetjs/cli
npm alternative
npm install -g @exetjs/cli

Verify that the executable is available:

Verify installation
exet --version

For manual integration in an existing ESM project, install @exetjs/core directly. For a new application, the CLI is the recommended starting point.

Quick start #

Create a project, enter its directory, and start development. The setup wizard asks for your package manager, server host, port, API prefix, and CORS origin.

Create your first API
exet init my-api
cd my-api
exet start

The CLI prints the resolved server address and health URL. Open the health URL or request it from your terminal. With port 5000 and the default API prefix:

Check the server
curl http://localhost:5000/api/v1/health
Your configuration determines the address.

Port 5000 is an example. Use the host and port you selected during setup, or the health URL printed by the CLI.

CLI commands #

A focused command set for the everyday development loop. Run project commands from the directory containing exet.config.ts.

exet init [projectName]

Create an Express + TypeScript project with an interactive setup.

Example
exet init my-api --no-install

exet start

Validate configuration and run the project using its local tsx installation.

Example
exet start --no-watch

exet install <moduleName>

Add a module template, update the registry and install its dependencies.

Example
exet install auth --dry-run

exet list

List the module templates available in the installed CLI version.

Example
exet list

exet doctor

Check project paths, runtime configuration, registry markers and health registration.

Example
exet doctor

exet install also supports --no-install to skip dependency installation and --force to allow overwriting template files. Review a dry run before replacing existing work.

Project structure #

The generated project separates runtime setup from feature modules. Routes and handlers live with their module; shared utilities have a dedicated home.

Generated project
my-api/
├── src/
│   ├── app.ts                # Application bootstrap
│   ├── main.ts               # Runtime entry point
│   ├── config/               # Environment and app config
│   ├── middlewares/          # Logging and error handling
│   ├── modules/
│   │   ├── index.ts          # Explicit module registry
│   │   └── health/           # Built-in health module
│   └── shared/               # Reusable utilities
├── .env
├── .env.example
├── exet.config.ts
├── package.json
└── tsconfig.json

src/app.ts creates the application, registers the modules, and starts the server. src/modules/index.ts is the explicit module registry. Keep the registry marker comments so the CLI can safely add new modules.

Runtime configuration #

Project defaults live in exet.config.ts. An environment file and process environment can override runtime values. The order is explicit:

Process environmentEnvironment fileProject defaults
.env example
HOST=0.0.0.0
PORT=5000
API_PREFIX=/api/v1
APP_NAME=my-api
NODE_ENV=development
CORS_ENABLED=true
CORS_ORIGIN=http://localhost:5173
LOG_LEVEL=info
Runtime environment variables
VariablePurpose
HOSTNetwork interface to bind to. Use 0.0.0.0 for a container or remote host.
PORTHTTP listening port for the application.
API_PREFIXBase path for registered API routes, usually /api/v1.
APP_NAMEApplication name used by the runtime.
NODE_ENVRuntime environment, such as development or production.
CORS_ENABLEDWhether CORS handling is enabled.
CORS_ORIGINAllowed origin for cross-origin requests.
LOG_LEVELLogging verbosity, for example info or debug.

The environment file path comes from paths.envFile. Set EXET_ENV_FILE to override that path for a specific process. New projects use HOST and PORT; the older APP_HOST and APP_PORT aliases are deprecated.

Modules #

See the module catalog for available modules and the Core module contract for the complete API.

A module declares its name, base path, and registration function. It returns an Express router, keeping ordinary Express routes and middleware available.

src/modules/hello/hello.module.ts
import { Router } from 'express';
import type { ExetModule } from '@exetjs/core';

export const helloModule: ExetModule = {
  name: 'hello',
  basePath: '/hello',
  register: () => {
    const router = Router();
    router.get('/', (_req, res) => {
      res.json({ message: 'Hello, ExetJS.' });
    });
    return { router };
  },
};

Add the module to the exported registry alongside the built-in health module:

src/modules/index.ts
import type { ExetModule } from '@exetjs/core';
import { healthModule } from './health/health.module.js';
import { helloModule } from './hello/hello.module.js';

// exet:imports:start
// exet:imports:end

export const modules: ExetModule[] = [
  healthModule,
  helloModule,
  // exet:modules:start
  // exet:modules:end
];

With the default prefix, the route is available at /api/v1/hello. To explore the templates included with your installed CLI, run exet list.

The auth template is a starting point.

Version 0.1.0 includes an authentication skeleton with in-memory persistence. Replace its repository and configure a strong JWT_SECRET before production use.

Health check #

Generated projects include a health module at the default endpoint:

GET/api/v1/healthapplication/json
Request
curl http://localhost:5000/api/v1/health

The handler returns HTTP 200 with an API response containing status: "ok", engine: "ExetJS", and a timestamp. Its path follows your configured API prefix.

Use it to check that the application is reachable. Add checks for your database and other dependencies if your deployment needs readiness checks beyond the built-in endpoint.

Deployment #

Deploy the generated backend to an environment that supports Node.js 24 or newer. Type-check and build the project, then run the compiled entry point using the production script.

Build and run (pnpm project)
pnpm check
pnpm build
pnpm start:prod

Set NODE_ENV=production and provide the runtime environment values through your host. Bind to HOST=0.0.0.0 where required, configure the assigned port, and set the intended CORS origin.

The production script runs node dist/main.js. Keep required runtime dependencies available and use your host's process supervision. The development command exet start is intended for the local workflow.

Frequently asked questions #

Does ExetJS replace Express?

No. ExetJS is built around Express. Modules return Express routers, and your application can use familiar routes and middleware.

Is a database included?

The core does not select a database for you. Add the persistence layer your application needs. The current auth template uses an in-memory repository that you should replace for production.

Can I use npm instead of pnpm?

Yes. The project wizard supports pnpm, npm, and Yarn. Use the package manager selected during setup for subsequent project commands.

How does ExetJS relate to NurJS?

ExetJS continues the project previously published as nurjs-core and nurjs-cli. New projects should use @exetjs/core and @exetjs/cli. The executable is now exet.

Where can I find the package source of truth?

The published core package and CLI package contain their READMEs and version-specific implementation. This guide follows version 0.1.0.

ExetJS v0.1.0Back to top ↑