Project Structure
When you bootstrap a new ExisJS project using create-exis, it generates a clean, opinionated folder structure designed for scalability and maintainability.
Unlike frameworks that force you into deeply nested architectural layers, ExisJS relies heavily on native File-System Routing and centralized configurations to keep your project lean.
The Default Structure
Here is a look at a standard ExisJS project structure:
my-exis-app/├── .exis/ # Internal framework cache and build artifacts├── src/│ └── http/│ ├── server.ts # The main backend entry point│ ├── route.ts # The root API routes (e.g. `GET /`)│ └── health/│ └── route.ts # Healthcheck endpoints (e.g. `GET /health`)├── .env # Local environment variables├── env.ts # Type-safe environment variable schema├── exis.config.ts # The ExisJS server configuration file├── package.json└── tsconfig.jsonKey Files & Directories
1. exis.config.ts
This is the brain of your application's infrastructure. Here, you define network ports, SSL certificates, global CORS policies, Helmet security, and register native framework Plugins (like GraphQL or Drizzle).
Read the full Configuration Guide
2. env.ts
ExisJS strongly encourages type-safe environment variables. By defining an env.ts file using the built-in validator (v.env()), your application will gracefully crash at boot if a required environment variable (like DATABASE_URL) is missing.
import { v } from 'exisjs/validator'
export const env = v.env(v.object({ PORT: v.string().optional(), NODE_ENV: v.enum(['development', 'production', 'test']), DATABASE_URL: v.string()}))3. src/http/server.ts
This is your application's bootstrap file. Instead of manually invoking app.listen(), you export your server configuration. The ExisJS CLI automatically reads this file, connects your plugins, mounts the file-system router, and starts the server.
import { exis } from 'exisjs'
export default exis({ async onStart(app) { // Connect to database, provide global DI services, etc. }, async onClose(app) { // Gracefully close connections }})4. src/http/**/route.ts
ExisJS uses File-System Routing out of the box! Any file named route.ts inside the src/http/ directory is automatically mapped to a URL based on its folder path. You can define routes functionally using controller({...}) or with OOP classes using @Controller().
src/http/route.tsmaps to/src/http/health/route.tsmaps to/healthsrc/http/users/settings/route.tsmaps to/users/settings
5. src/http/**/gateway.ts
Gateways allow you to apply configurations to entire folders. If you place a gateway.ts file inside src/http/admin/, the Guards, Middlewares, and Providers defined in that Gateway will automatically apply to every single route inside /admin/*. Like servers, these can be built using defineGateway({...}) or the @Gateway() decorator.
6. .exis/
This is an internal, hidden directory generated by the ExisJS CLI. It holds compiled router mappings and runtime cache to ensure your application boots up instantaneously. You should add .exis/ to your .gitignore.
The ExisJS CLI
Your project is driven entirely by the exis CLI tool, which is typically mapped in your package.json scripts:
exis dev: Starts the development server with blazing fast Hot-Module Replacement (HMR).exis build: Compiles your TypeScript code to highly optimized JavaScript for production.exis start: Starts the production server using the compiled output.exis routes: Prints a beautiful table of every compiled API endpoint and WebSocket in your application.exis generate <type>: Scaffolds new routes, plugins, or middleware boilerplate instantly.