ExisJS

Installation & Setup

This guide provides step-by-step instructions for creating a new ExisJS application with the create-exisjs scaffolding tool or installing the framework manually into an existing TypeScript project.


Prerequisites

Before starting, ensure your system satisfies the following requirements:

  • Node.js: v20.0.0 or higher
  • Package Manager: npm (v10+), pnpm (v9+), yarn (v1.22+ or berry), or bun (v1.0+)
  • Operating System: macOS, Linux, or Windows (x64 and ARM64 architectures supported)

Verify your Node.js version by running:

node -v

Scaffolding a New Project

The quickest way to start a new ExisJS project is with the official create-exisjs scaffolding tool.

Interactive Scaffolding

Run the creation command using your preferred package manager:

# npmnpm create exisjs@latest my-api
# pnpmpnpm create exisjs my-api
# yarnyarn create exisjs my-api
# bunbun create exisjs my-api

Yarn 1 can't take a version tag in yarn create. To try a prerelease with Yarn 1, run npx create-exisjs@alpha my-api, then yarn install in the project. Yarn 1 also installs optional dependencies despite --ignore-optional, so a yarn install --production still includes @exisjs/cli and its build tools; use npm ci --omit=dev --omit=optional for production images.

The CLI prompts you with configuration options:

Terminal
? What is your project named? › my-api? Would you like to use TypeScript? › Yes / No? Would you like to use ESLint? › Yes / No? Which routing paradigm do you prefer? › Functional (Default) / Class-Based (OOP)? Would you like to customize the import alias (`@/*` by default)? › No / Yes

Non-Interactive Command-Line Flags

For automated environments, Docker initialization, or CI/CD pipelines, you can pass command-line flags to skip interactive prompts:

npx create-exisjs@latest my-api --ts --functional --eslint --yes

npx create-exisjs@latest --help lists every flag.

Complete CLI Flag Reference

FlagDescriptionDefault
--ts, --typescriptConfigure project with TypeScripttrue
--js, --javascriptConfigure project with plain JavaScriptfalse
--functionalConfigure project using functional paradigm (controller(), route.*)true
--oopConfigure project using class-based decorator paradigm (@Controller(), @Get())false
--eslintGenerate ESLint flat config with TypeScript rulestrue
--no-eslintSkip ESLint setupfalse
--skip-installScaffold directory tree and templates without installing dependenciesfalse
--skip-gitSkip automatic git init initializationfalse
--yes, -yAccept default configuration non-interactivelyfalse
--use-pnpmForce dependency installation via pnpmAuto-detected
--use-bunForce dependency installation via bunAuto-detected
--use-yarnForce dependency installation via yarnAuto-detected
--use-npmForce dependency installation via npmAuto-detected

Generated Project Layout

Once the scaffolding finishes, your project contains the standard ExisJS directory layout:

my-api/├── .agents/│   └── rules/│       └── AGENTS.md            # Architecture rules and agent guidelines├── src/│   ├── common/│   │   └── guards/│   │       └── auth.guard.ts    # Reusable route guards│   ├── config/│   │   └── env.ts               # Type-safe environment validation (tex.env)│   ├── cron/│   │   └── cleanup.ts           # Scheduled background tasks│   ├── database/│   │   └── db.ts                # Database lifecycle and connection│   └── http/│       ├── health/│       │   └── route.ts         # Health check endpoint (/health)│       ├── users/│       │   ├── route.ts         # User routes (/users)│       │   ├── schema.ts        # Input validation schemas (tex.*)│       │   └── service.ts       # Service layer logic│       ├── boundary.ts          # Root middleware, CORS & error boundary│       ├── route.ts             # Root route handler (/)│       └── server.ts            # Application lifecycle (onStart / onClose)├── tests/│   └── users.test.ts        # End-to-end test suite├── .env                         # Environment variables├── .gitignore├── .prettierrc├── eslint.config.mjs            # ESLint configuration (when selected)├── exis.config.ts               # Framework configuration├── package.json└── tsconfig.json

Manual Installation

To install ExisJS into an existing repository without scaffolding:

Step 1: Install Core Dependencies

npm install exisjsnpm install -D @exisjs/cli typescript @types/node prettier

Step 2: Configure tsconfig.json

Create or update tsconfig.json to configure module resolution and metadata reflection:

tsconfig.json
{  "compilerOptions": {    "target": "ES2022",    "lib": ["esnext"],    "allowJs": true,    "skipLibCheck": true,    "strict": true,    "esModuleInterop": true,    "experimentalDecorators": true,    "emitDecoratorMetadata": true,    "module": "esnext",    "moduleResolution": "bundler",    "resolveJsonModule": true,    "isolatedModules": true,    "noEmit": true,    "paths": {      "@/*": ["./src/*"]    },    "types": ["node"]  },  "include": [    "src/**/*.ts",    "tests/**/*.ts",    "*.config.ts",    "*.ts"  ],  "exclude": ["node_modules", ".exis", "dist", "build"]}
DEFAULT

[!NOTE] experimentalDecorators is required when using the class-based (OOP) paradigm; emitDecoratorMetadata is harmless but not used by the ExisJS toolchain, so inject constructor dependencies with @Inject(Token). This applies to the class-based (OOP) paradigm (@Controller(), @Injectable()).

Step 3: Create exis.config.ts

Create an exis.config.ts file in the project root:

exis.config.ts
import type { ExisConfig } from 'exisjs/config'
const config: ExisConfig = {  port: Number(process.env.PORT) || 4000,  host: '0.0.0.0',
  // Credentialed requests need explicit origins (comma-separated CORS_ORIGIN).  // Without it, any origin may call the API, but without cookies.  cors: process.env.CORS_ORIGIN    ? { origin: process.env.CORS_ORIGIN.split(','), credentials: true }    : { origin: '*' },
  logger: {    level: process.env.NODE_ENV === 'production' ? 'info' : 'debug',    pretty: process.env.NODE_ENV !== 'production',  },
  helmet: { enabled: true },  compression: true,
  // Swagger UI at /docs, development only  docs: { enabled: process.env.NODE_ENV !== 'production' },}
export default config

Step 4: Configure NPM Scripts

Add the standard ExisJS CLI commands to package.json:

package.json
{  "scripts": {    "dev": "exisjs dev",    "build": "exisjs build",    "start": "exisjs start",    "routes": "exisjs routes",    "test": "exisjs test",    "doctor": "exisjs doctor"  }}

Verifying the Installation

1. Create a Health Check Endpoint

Create src/http/health/route.ts:

Option A: Functional Route

src/http/health/route.ts
import { controller, route } from 'exisjs/router'
export default controller({  check: route.get('/', {    summary: 'Service health check',    handle: () => ({      status: 'ok',      timestamp: new Date().toISOString(),    }),  }),})

Option B: Class-Based Route

src/http/health/route.ts
import { Controller, Get, ApiOperation } from 'exisjs/decorators'
@Controller()export default class HealthController {  @Get('/')  @ApiOperation({ summary: 'Service health check' })  check() {    return {      status: 'ok',      timestamp: new Date().toISOString(),    }  }}

2. Start the Development Server

Execute the dev script:

npm run dev

Output:

Terminal
[exis] starting development server (v0.9.0)...EXIS ready in 125 ms
→ Local:   http://localhost:4000/→ Docs:    http://localhost:4000/docs→ Network: http://127.0.0.1:4000/

3. Verify the Endpoint

Send an HTTP GET request to verify the route:

curl http://localhost:4000/health

Expected JSON response:

{  "status": "ok",  "timestamp": "2026-10-02T11:35:00.000Z"}

Open http://localhost:4000/docs in your browser to inspect the interactive Swagger UI.


Next Steps

  • Project Structure: Review directory conventions for routes, boundaries, services, and database models.
  • Routing & Endpoints: Learn how folders map to HTTP verbs, path params, and catch-all routes.
  • Validation: Build typed schemas with tex for body, query, and header validation.
  • Configuration Reference: Complete reference of all options in exis.config.ts.