CLI Examples ​
This guide walks you through creating your first Asena project from scratch, including creating components and building for production.
Prerequisites ​
- Bun runtime v1.2.8 or higher
- Asena CLI installed globally
Verify installations:
bun --version
asena --versionStep 1: Install Asena CLI ​
If you haven't installed the CLI yet:
bun install -g @asenajs/asena-cliVerify installation:
asena --versionStep 2: Create a New Project ​
Create a new Asena project with interactive prompts:
asena createAnswer the prompts:
✔ Enter your project name: my-asena-app
✔ Select adapter: Ergenecore
✔ Do you want to setup logger? Yes
✔ Do you want to setup ESLint? Yes
✔ Do you want to setup Prettier? Yes
â ™ Creating asena project...Adapter Selection
- Ergenecore - Bun-native adapter with zero dependencies (recommended)
- Hono - Hono framework-based adapter with ecosystem compatibility
SSH or CI/CD Environment?
If you're working over SSH or in a CI/CD pipeline, interactive prompts won't work. Use non-interactive mode instead:
# Create project with all options via CLI arguments
asena create my-asena-app --adapter=ergenecore --logger --eslint --prettierStep 3: Verify Project Setup ​
Navigate to your project directory:
cd my-asena-appStart the development server:
asena dev startYou should see output like this:
Build completed successfully.
2025-10-15 14:30:19 [info]:
___ _____ ______ _ __ ___
/ | / ___/ / ____// | / // |
/ /| | \__ \ / __/ / |/ // /| |
/ ___ | ___/ // /___ / /| // ___ |
/_/ |_|/____//_____//_/ |_//_/ |_|
2025-10-15 14:30:20 [info]: Adapter: ErgenecoreAdapter implemented
2025-10-15 14:30:20 [info]: All components registered and ready to use
2025-10-15 14:30:20 [info]: No configs found
2025-10-15 14:30:20 [info]: Controller: AsenaController found:
2025-10-15 14:30:20 [info]: Successfully registered GET route for PATH: /
2025-10-15 14:30:20 [info]: Controller: AsenaController successfully registered.
2025-10-15 14:30:20 [info]: No websockets found
2025-10-15 14:30:20 [info]: Server started on port 3000Test the default endpoint:
curl http://localhost:3000/You should see: Hello asena
Step 4: Create a Controller ​
Generate a new controller:
asena g cEnter the controller name when prompted:
✔ Enter controller name: UserThis creates src/controllers/UserController.ts. Let's modify it:
For Ergenecore Adapter ​
import { Controller } from '@asenajs/asena/server';
import { Get } from '@asenajs/asena/web';
import type { Context } from '@asenajs/ergenecore/types';
@Controller('/users')
export class UserController {
@Get({ path: '/' })
async getAllUsers(context: Context) {
return context.send({
message: 'List of all users',
users: [
{ id: 1, name: 'John Doe' },
{ id: 2, name: 'Jane Smith' }
]
});
}
@Get({ path: '/:id' })
async getUserById(context: Context) {
const id = context.getParam('id');
return context.send({
message: `User with ID: ${id}`,
user: { id, name: 'John Doe' }
});
}
}For Hono Adapter ​
import { Controller } from '@asenajs/asena/server';
import { Get } from '@asenajs/asena/web';
import type { Context } from '@asenajs/hono-adapter/types';
@Controller('/users')
export class UserController {
@Get({ path: '/' })
async getAllUsers(context: Context) {
return context.send({
message: 'List of all users',
users: [
{ id: 1, name: 'John Doe' },
{ id: 2, name: 'Jane Smith' }
]
});
}
@Get({ path: '/:id' })
async getUserById(context: Context) {
const id = context.getParam('id');
return context.send({
message: `User with ID: ${id}`,
user: { id, name: 'John Doe' }
});
}
}Restart the development server:
asena dev startYou should see the new routes registered:
2025-10-15 14:35:27 [info]: Controller: UserController found:
2025-10-15 14:35:27 [info]: Successfully registered GET route for PATH: /users
2025-10-15 14:35:27 [info]: Successfully registered GET route for PATH: /users/:id
2025-10-15 14:35:27 [info]: Controller: UserController successfully registered.Test the new endpoints:
# Get all users
curl http://localhost:3000/users
# Get user by ID
curl http://localhost:3000/users/1Controller Names in Output
Controller names are visible in logs when buildOptions.minify.identifiers is set to false in asena.config.ts.
Step 5: Create a Service ​
Generate a service for business logic:
asena g sEnter the service name:
✔ Enter service name: UserEdit src/services/UserService.ts:
import { Service } from '@asenajs/asena/server';
interface User {
id: number;
name: string;
email: string;
}
@Service()
export class UserService {
private users: User[] = [
{ id: 1, name: 'John Doe', email: 'john@example.com' },
{ id: 2, name: 'Jane Smith', email: 'jane@example.com' }
];
async getAllUsers(): Promise<User[]> {
return this.users;
}
async getUserById(id: number): Promise<User | undefined> {
return this.users.find(user => user.id === id);
}
async createUser(name: string, email: string): Promise<User> {
const newUser: User = {
id: this.users.length + 1,
name,
email
};
this.users.push(newUser);
return newUser;
}
}Update your controller to use the service:
import { Controller } from '@asenajs/asena/server';
import { Get, Post } from '@asenajs/asena/web';
import { Inject } from '@asenajs/asena/ioc';
import type { Context } from '@asenajs/ergenecore/types';
import { UserService } from '../services/UserService';
@Controller('/users')
export class UserController {
@Inject(UserService)
private userService: UserService;
@Get({ path: '/' })
async getAllUsers(context: Context) {
const users = await this.userService.getAllUsers();
return context.send({ users });
}
@Get({ path: '/:id' })
async getUserById(context: Context) {
const id = parseInt(context.getParam('id'));
const user = await this.userService.getUserById(id);
if (!user) {
return context.send({ error: 'User not found' }, 404);
}
return context.send({ user });
}
@Post({ path: '/' })
async createUser(context: Context) {
const { name, email } = await context.getBody();
const user = await this.userService.createUser(name, email);
return context.send({ user }, 201);
}
}Test the new endpoints:
# Get all users
curl http://localhost:3000/users
# Get user by ID
curl http://localhost:3000/users/1
# Create a new user
curl -X POST http://localhost:3000/users \
-H "Content-Type: application/json" \
-d '{"name":"Bob Johnson","email":"bob@example.com"}'Step 6: Build for Production ​
Build your project:
asena buildOutput:
Build completed successfully.
Output: dist/index.jsThe build files are in the dist/ directory (configured in asena.config.ts).
Run the production build:
bun dist/index.asena.jsBuild Output
The CLI automatically discovers and bundles all your components. No manual imports needed!
Step 7: Add Middleware (Optional) ​
Generate a middleware:
asena g mEnter the middleware name:
✔ Enter middleware name: LoggerEdit src/middlewares/LoggerMiddleware.ts:
import { Middleware } from '@asenajs/asena/server';
import { MiddlewareService, type Context } from '@asenajs/ergenecore';
@Middleware()
export class LoggerMiddleware extends MiddlewareService {
async handle(context: Context, next: () => Promise<void>) {
const start = Date.now();
const method = context.getRequest().method;
const url = context.getRequest().url;
console.log(`[${method}] ${url} - Started`);
await next();
const duration = Date.now() - start;
console.log(`[${method}] ${url} - Completed in ${duration}ms`);
}
}Apply it to your controller:
@Controller('/users', { middlewares: [LoggerMiddleware] })
export class UserController {
// ... your routes
}Project Structure ​
Your project should now look like this:
my-asena-app/
├── src/
│ ├── controllers/
│ │ ├── AsenaController.ts # Default controller
│ │ └── UserController.ts # Your controller
│ ├── services/
│ │ └── UserService.ts # Your service
│ ├── middlewares/
│ │ └── LoggerMiddleware.ts # Your middleware
│ └── index.ts # Entry point
├── dist/ # Build output
├── asena.config.ts # CLI configuration
├── package.json
└── tsconfig.jsonNext Steps ​
Now that you've created your first Asena application:
- Learn about Controllers
- Explore Services
- Understand Middleware
- Set up Database integration
- Configure WebSocket
- Deploy to Production
Related Documentation:
- CLI Commands - All CLI commands
- CLI Configuration - Configure your project
- Get Started Guide - Complete guide
- Adapters - Learn about adapters