A TypeScript Server Infrastructure combining enterprise-grade patterns with high performance.
Ignis brings together the structured, enterprise development experience of LoopBack 4 with the blazing speed and simplicity of Hono - giving you the best of both worlds.
- β‘ High Performance - Built on Hono, one of the fastest web frameworks
- ποΈ Enterprise Architecture - Layered architecture with Controllers, Services, and Repositories
- π Dependency Injection - Built-in DI container for loosely coupled, testable code
- π Type Safety - Full TypeScript support with excellent type inference
- π Auto-Generated API Docs - OpenAPI/Swagger documentation out of the box
- ποΈ Database ORM - Integrated with Drizzle ORM for type-safe database operations
- π§© Component-Based - Modular, reusable components (Authentication, Logging, Health Checks, etc.)
- π― Decorator-Based Routing - Clean, declarative route definitions with
@get,@post, etc. - β Built-in Validation - Zod schema validation for requests and responses
- π Multi-Runtime - Works on Node.js, Bun, Deno, and Cloudflare Workers
- When Should You Use Ignis?
- Prerequisites
- Installation
- Quick Start
- Project Structure
- Available Scripts
- Core Concepts
- Documentation
- Examples
- Contributing
- License
- E-commerce Backends - Complex business logic, multiple controllers, auth, payments
- SaaS Platform APIs - Multi-tenant architecture, modular components
- Enterprise Tools - Team collaboration with clear architectural patterns
- Growing APIs - 10+ endpoints that need structure and maintainability
- Simple Proxies/Webhooks - Too much structure for tiny services
- Quick Prototypes - Use plain Hono for maximum speed
- 3-5 Endpoint APIs - Consider plain Hono unless you plan to grow
| Aspect | Minimal (Hono, Express) | Enterprise (NestJS, LoopBack) | Ignis |
|---|---|---|---|
| Performance | β‘ ~150k req/s | ~25k req/s | β‘ ~140k req/s |
| Architecture | Flexible (DIY) | Strict conventions | Guided conventions |
| Learning Curve | Low | High | Medium |
| Dependency Injection | Manual/3rd party | Built-in (complex) | Built-in (simple) |
| Community | Large (Express) / Growing (Hono) | Very large | Small (new) |
| Best For | Microservices, serverless | Large teams, enterprise | Growing APIs, small teams |
Choose wisely: Each approach has genuine strengths. See Philosophy for detailed comparison.
Before starting with Ignis, ensure you have:
| Tool | Version | Purpose |
|---|---|---|
| Bun | β₯ 1.3.0 | JavaScript runtime (recommended) |
| Node.js | β₯ 18.x | Alternative runtime (optional) |
| PostgreSQL | β₯ 14.x | Database server |
Bun (Recommended):
# macOS/Linux
curl -fsSL https://bun.sh/install | bash
# Windows (requires WSL)
# Install WSL first, then run the command abovePostgreSQL:
# macOS
brew install postgresql@14
# Ubuntu/Debian
sudo apt-get install postgresql-14
# Windows
# Download from https://www.postgresql.org/download/windows/Verify Installation:
bun --version # Expected: 1.3.0 or higher
psql --version # Expected: psql (PostgreSQL) 14.x or highermkdir my-ignis-app
cd my-ignis-app
bun init -yProduction Dependencies:
bun add hono @hono/zod-openapi @scalar/hono-api-reference @venizia/ignis dotenv-flow
bun add drizzle-orm drizzle-zod pg lodashDevelopment Dependencies:
bun add -d typescript @types/bun @venizia/dev-configs
bun add -d tsc-alias tsconfig-paths
bun add -d drizzle-kit @types/pg @types/lodashTypeScript - Create tsconfig.json:
{
"$schema": "http://json.schemastore.org/tsconfig",
"extends": "@venizia/dev-configs/tsconfig.common.json",
"compilerOptions": {
"outDir": "dist",
"rootDir": "src",
"baseUrl": "src",
"paths": {
"@/*": ["./*"]
}
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
}ESLint - Create eslint.config.mjs:
import { eslintConfigs } from "@venizia/dev-configs";
export default eslintConfigs;Prettier - Create .prettierrc.mjs:
import { prettierConfigs } from "@venizia/dev-configs";
export default prettierConfigs;Create .prettierignore:
dist
node_modules
*.log
.*-audit.json
Create index.ts:
import { z } from "@hono/zod-openapi";
import {
BaseApplication,
BaseController,
controller,
get,
HTTP,
IApplicationInfo,
jsonContent,
} from "@venizia/ignis";
import { Context } from "hono";
import appInfo from "./../package.json";
// 1. Define a controller
@controller({ path: "/hello" })
class HelloController extends BaseController {
constructor() {
super({ scope: "HelloController", path: "/hello" });
}
// NOTE: This is a function that must be overridden.
override binding() {
// Bind dependencies here (if needed)
// Extra binding routes with functional way, use `bindRoute` or `defineRoute`
}
@get({
configs: {
path: "/",
method: HTTP.Methods.GET,
responses: {
[HTTP.ResultCodes.RS_2.Ok]: jsonContent({
description: "Says hello",
schema: z.object({ message: z.string() }),
}),
},
},
})
sayHello(c: Context) {
return c.json({ message: "Hello from Ignis!" }, HTTP.ResultCodes.RS_2.Ok);
}
}
// 2. Create the application
class App extends BaseApplication {
getAppInfo(): IApplicationInfo {
return appInfo;
}
staticConfigure() {
// Static configuration before dependency injection
}
preConfigure() {
this.controller(HelloController);
}
postConfigure() {
// Configuration after all bindings are complete
}
setupMiddlewares() {
// Custom middleware setup (optional)
}
}
// 3. Start the server
const app = new App({
scope: "App",
config: {
host: "0.0.0.0",
port: 3000,
path: { base: "/api", isStrict: false },
},
});
app.start();bun run index.tsTest the endpoint:
curl http://localhost:3000/api/hello
# Response: {"message":"Hello from Ignis!"}View API Documentation:
Open http://localhost:3000/doc/explorer in your browser to see interactive Swagger UI documentation!
For production applications, organize your code like this:
my-ignis-app/
βββ src/
β βββ application.ts # Application configuration
β βββ index.ts # Entry point
β βββ controllers/ # HTTP request handlers
β β βββ todo.controller.ts
β βββ services/ # Business logic
β β βββ todo.service.ts
β βββ repositories/ # Data access layer
β β βββ todo.repository.ts
β βββ models/ # Database models
β β βββ todo.model.ts
β βββ datasources/ # Database connections
β β βββ postgres.datasource.ts
β βββ components/ # Reusable modules
β βββ auth.component.ts
βββ scripts/
β βββ clean.sh # Cleanup script
βββ package.json
βββ tsconfig.json # Extends @venizia/dev-configs/tsconfig.common.json
βββ eslint.config.mjs # Uses eslintConfigs from @venizia/dev-configs
βββ .prettierrc.mjs # Uses prettierConfigs from @venizia/dev-configs
Add these scripts to your package.json:
| Script | Command | Description |
|---|---|---|
| Development | ||
server:dev |
NODE_ENV=development bun . |
Start development server |
rebuild |
bun run clean && bun run build |
Clean and rebuild project |
| Building | ||
build |
tsc -p tsconfig.json && tsc-alias -p tsconfig.json |
Compile TypeScript to JavaScript |
compile:linux |
bun build --compile --minify --sourcemap --target=bun-linux-x64 ./src/index.ts --outfile ./dist/my_app |
Create standalone binary for Linux |
clean |
sh ./scripts/clean.sh |
Remove build artifacts |
| Database | ||
migrate:dev |
NODE_ENV=development drizzle-kit push --config=src/migration.ts |
Apply database migrations |
generate-migration:dev |
NODE_ENV=development drizzle-kit generate --config=src/migration.ts |
Generate migration files |
| Code Quality | ||
lint |
bun run eslint && bun run prettier:cli |
Check code style |
lint:fix |
bun run eslint --fix && bun run prettier:fix |
Auto-fix code style issues |
eslint |
eslint --report-unused-disable-directives . |
Run ESLint |
prettier:cli |
prettier "**/*.{js,ts}" -l |
Check formatting |
prettier:fix |
prettier "**/*.{js,ts}" --write |
Auto-format code |
| Production | ||
server:prod |
NODE_ENV=production bun . |
Start production server |
{
"scripts": {
"lint": "bun run eslint && bun run prettier:cli",
"lint:fix": "bun run eslint --fix && bun run prettier:fix",
"prettier:cli": "prettier \"**/*.{js,ts}\" -l",
"prettier:fix": "bun run prettier:cli --write",
"eslint": "eslint --report-unused-disable-directives .",
"build": "tsc -p tsconfig.json && tsc-alias -p tsconfig.json",
"compile:linux": "bun build --compile --minify --sourcemap --target=bun-linux-x64 ./src/index.ts --outfile ./dist/my_app",
"clean": "sh ./scripts/clean.sh",
"rebuild": "bun run clean && bun run build",
"migrate:dev": "NODE_ENV=development drizzle-kit push --config=src/migration.ts",
"generate-migration:dev": "NODE_ENV=development drizzle-kit generate --config=src/migration.ts",
"preserver:dev": "bun run rebuild",
"server:dev": "NODE_ENV=development bun .",
"server:prod": "NODE_ENV=production bun ."
}
}βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β HTTP Request β
β GET /api/todos/:id β
ββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββ
β
βΌ
ββββββββββββββββββββ
β Controller β β Handles HTTP, validates input
β @get('/...') β
βββββββββββ¬βββββββββ
β calls service/repository
βΌ
ββββββββββββββββββββ
β Service β β Business logic (optional)
β (optional) β
βββββββββββ¬βββββββββ
β uses repository
βΌ
ββββββββββββββββββββ
β Repository β β Type-safe data access
β findById(id) β
βββββββββββ¬βββββββββ
β uses dataSource
βΌ
ββββββββββββββββββββ
β DataSource β β Database connection
β (Drizzle ORM) β
βββββββββββ¬βββββββββ
β executes SQL
βΌ
ββββββββββββββββββββ
β PostgreSQL β β Database
ββββββββββββββββββββ
- Controllers - Handle HTTP requests and responses
- Services - Contain business logic (optional layer)
- Repositories - Abstract data access operations
- DataSources - Manage database connections
- Models - Define data structures and schemas
- Components - Reusable, pluggable modules
Ignis uses decorator-based dependency injection:
@controller({ path: "/todos" })
export class TodoController extends BaseController {
constructor(
@inject("repositories.TodoRepository")
private todoRepository: TodoRepository,
) {
super({ scope: "TodoController", path: "/todos" });
}
}Online Documentation: https://venizia-ai.github.io/ignis
Comprehensive documentation is also available in the packages/docs/wiki directory:
- Philosophy - Understand the "why" behind Ignis
- Prerequisites - Required tools and setup
- 5-Minute Quickstart - Fastest path to a working API
- Complete Setup Guide - Production-ready setup
- Building a CRUD API - Complete tutorial
Run the documentation server locally:
bun run docs:devThen visit http://localhost:5173 in your browser.
See Building a CRUD API for a full tutorial on creating a Todo API with:
- Database models and migrations
- Repository pattern for data access
- Auto-generated CRUD endpoints
- Request/response validation
- OpenAPI documentation
@post({
configs: {
path: '/todos',
request: {
body: jsonContent({
schema: z.object({
title: z.string().min(1),
description: z.string().optional(),
}),
}),
},
responses: {
[HTTP.ResultCodes.RS_2.Created]: jsonContent({
schema: z.object({
id: z.string(),
title: z.string(),
description: z.string().nullable(),
isCompleted: z.boolean(),
}),
}),
},
},
})
async createTodo(c: Context) {
const body = await c.req.json();
const todo = await this.todoRepository.create(body);
return c.json(todo, HTTP.ResultCodes.RS_2.Created);
}Contributions are welcome! Please read our:
- Contributing Guide - How to contribute
- Code of Conduct - Community guidelines
- Security Policy - Reporting vulnerabilities
# Clone the repository
git clone https://github.com/venizia-ai/ignis.git
cd ignis
# Install dependencies
bun install
# Rebuild core packages
bun run rebuild:ignis
# Run documentation
bun run docs:devThis project is licensed under the MIT License - see the LICENSE.md file for details.
Ignis is inspired by:
- LoopBack 4 - Enterprise patterns and architecture
- Hono - Performance and modern API design
- Documentation: https://venizia-ai.github.io/ignis
- GitHub Issues: https://github.com/VENIZIA-AI/ignis/issues
- Author: VENIZIA AI Developer developer@venizia.ai
Built with β€οΈ using TypeScript, Hono, and enterprise patterns.