Getting Started
In this guide, you'll learn the core fundamentals of ExisJS. To get familiar with the essential building blocks, we'll scaffold a new project, explore the file structure, and create our very first API server.
We recommend TypeScript for type-safety and automatic frontend client generation. However, ExisJS fully supports vanilla JavaScript as well. ExisJS leverages esbuild under the hood, meaning you do not need to manually run tsc to start your server.
Prerequisites
Please make sure that Node.js (version >= 20) is installed on your operating system.
Setup
Setting up a new project can be done using our CLI tool. Open your terminal and run the following command to scaffold a new ExisJS project:
You can also use your package manager of choice:
# npm$ npm create exisjs@latest my-backend
# pnpm$ pnpm create exisjs my-backend
# yarn$ yarn create exisjs my-backend
# bun$ bun create exisjs my-backend
# npx$ npx create-exisjs@latest my-backendThe CLI will prompt you with a few simple questions to customize your project:
√ Would you like to use TypeScript? ... No / Yes√ Would you like to use ESLint? ... No / Yes√ Would you like your code inside a `src/` directory? ... No / Yes√ Would you like to customize the import alias (`@/*` by default)? ... No / Yes
Creating a new Exis JS app in my-backend.The CLI will then create the my-backend directory, install all required dependencies, and populate the project with a conventional base structure.
Core Files
Once the installation is complete, your project directory will look something like this:
The root configuration for your application (CORS, Logger, Port).
Your First Server
Let's look at the generated src/http/server.ts. This is the strict entry point of your application, where you can connect to databases and register global plugins.
Functional Server Setup
import { exis } from 'exisjs'
export default exis({ async onStart(app) { // 1. Connect to your database // await db.connect() // 2. Register plugins // app.plugin(authPlugin) // The Exis CLI automatically boots the server and file-system routes },
async onClose(app) { // Gracefully close database connections here // await db.disconnect() },})Class-Based (OOP) Server Setup
import { Server } from 'exisjs/decorators'import type { App } from 'exisjs'
@Server()export default class RootServer { async onStart(app: App) { // 1. Connect to your database // await db.connect() // 2. Register plugins // app.plugin(authPlugin) // The Exis CLI automatically boots the server and file-system routes }
async onClose(app: App) { // Gracefully close database connections here // await db.disconnect() }}With ExisJS, the framework automatically handles booting up your server and loading your routes based on the file system. You don't need to manually call app.listen()!
Your First Route
ExisJS uses folder-based routing. Your API structure maps directly to your folders in src/http/.
ExisJS supports two primary styles of writing routes: Functional and OOP (Class-based). You are free to use whichever paradigm fits your team best.
Functional Routing
Functional routing provides a lean, inference-heavy developer experience similar to modern frontend frameworks. Let's declare our first route in src/http/users/route.ts:
import { controller, route } from 'exisjs/router'
export default controller({ getUsers: route.get('/', { handle(req) { // Return a realistic response structure return { data: [ { id: 1, name: 'Alice' }, { id: 2, name: 'Bob' } ], total: 2 } }, }),})OOP Routing
If you prefer a highly-structured architecture heavily inspired by Angular and NestJS, ExisJS natively provides robust class-based routing using Decorators:
import { Controller, Get, Req } from 'exisjs/decorators'import type { Request } from 'exisjs'
@Controller()export default class UsersController { @Get('/') getUsers(@Req() req: Request) { // Return a realistic response structure return { data: [ { id: 1, name: 'Alice' }, { id: 2, name: 'Bob' } ], total: 2 } }}In both examples, because this file is named route.ts and is located in the users folder, it automatically responds to GET /users requests. Whatever you return is automatically serialized to JSON.
Running the Application
Your generated package.json comes pre-configured with the Exis CLI commands. Start the development server with hot-reload by running:
You will see the server boot up in your terminal:
6:18:28 pm [exis] starting development server (v0.1.0)...
EXIS v0.1.0 ready in 125 ms
→ Local: http://localhost:4000/ → Network: http://10.39.14.177:4000/ → Environ: development → press h + enter to show helpOpen your browser and navigate to http://localhost:4000/ (or the port defined in your .env). You will see:
{ "data": [ { "id": 1, "name": "Alice" }, { "id": 2, "name": "Bob" } ], "total": 2}