Enterprise-grade TypeScript server infrastructure built on Hono.
| Package | Latest Version | Next Version |
|---|---|---|
@venizia/ignis |
||
@venizia/ignis-boot |
||
@venizia/ignis-inversion |
||
@venizia/ignis-helpers |
||
@venizia/dev-configs |
||
@venizia/ignis-docs |
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. Think LoopBack 4's decorator-driven DI, repository pattern, and component system, running on Hono's ~140k req/s engine with Drizzle ORM's type-safe SQL.
Getting Started • Documentation • Examples • Contributing
- Key Features
- When Should You Use Ignis?
- Framework Comparison
- Monorepo Packages
- Prerequisites
- Installation
- Quick Start
- Architecture Flow
- Application Lifecycle
- Built-in Components
- Helpers Ecosystem
- Project Structure
- Monorepo Development
- Examples
- FAQ
- Documentation
- Contributing
- License
- High Performance -- Built on Hono, one of the fastest web frameworks (~140k req/s on Bun)
- Enterprise Architecture -- Layered architecture with Controllers, Services, Repositories, and DataSources
- Dependency Injection -- Lightweight IoC container (~350 lines) with constructor and property injection
- Type Safety -- Full TypeScript with Drizzle ORM type inference and Zod validation
- Auto-Generated API Docs -- OpenAPI/Swagger documentation out of the box via
@hono/zod-openapi - Decorator-Based Routing -- Clean, declarative route definitions with
@get,@post,@controller - Component System -- Pluggable modules for Auth (JWT/Basic), Health Checks, Swagger, Mail, Socket.IO, Static Assets
- Convention-Based Boot -- Auto-discovers controllers, services, repositories, datasources by file conventions
- Production Utilities -- Logger, Redis, BullMQ queues, MinIO storage, Crypto, Cron, Snowflake UID, and more
- Multi-Runtime -- Primary support for Bun, secondary support for Node.js
- 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) |
| ORM | BYO | TypeORM / Prisma | Drizzle (type-safe SQL) |
| OpenAPI Docs | Manual setup | Swagger module | Auto-generated |
| Auth | BYO | Passport / Guards | JWT + Basic built-in |
| Community | Large (Express) / Growing (Hono) | Very large | Growing |
| Best For | Microservices, serverless | Large teams, enterprise | Growing APIs, small teams |
@controller({ path: '/users' })
export class UserController extends BaseController {
constructor(
@inject({ key: 'repositories.UserRepository' }) private userRepo: UserRepository,
) {
super({ scope: 'UserController', path: '/users' });
}
@get({
configs: {
path: '/:id',
method: HTTP.Methods.GET,
request: { params: z.object({ id: z.string() }) },
responses: jsonResponse({
description: 'Get user by ID',
schema: z.object({ id: z.string(), name: z.string(), email: z.string() }),
}),
},
})
async findById(c: TRouteContext) {
const { id } = c.req.valid('param');
const user = await this.userRepo.findById({ id });
return c.json(user, HTTP.ResultCodes.RS_2.Ok);
}
}Tip
See the Philosophy page for detailed Express vs NestJS vs Ignis code comparisons.
+-------------------+
| dev-configs | Shared ESLint / Prettier / TypeScript configs
+--------+----------+
|
+--------v----------+
| inversion | IoC container, @inject, @injectable
+--------+----------+
|
+--------v----------+
| helpers | Logger, Redis, Queue, Storage, Crypto, ...
+--------+----------+
|
+--------v----------+
| boot | Convention-based auto-discovery & bootstrapping
+--------+----------+
|
+--------v----------+
| core | Application, Controllers, Repositories, Components
+-------------------+
Each package builds on the previous. Changing inversion affects everything downstream.
| Package | npm | Description |
|---|---|---|
| @venizia/ignis | @venizia/ignis |
Main framework -- Application, Controllers, Repositories, Models, DataSources, Components, Auth |
| @venizia/ignis-boot | @venizia/ignis-boot |
Convention-based auto-discovery and bootstrapping (configure -> discover -> load) |
| @venizia/ignis-inversion | @venizia/ignis-inversion |
Standalone DI/IoC container (~350 lines) -- Container, Binding, MetadataRegistry, decorators |
| @venizia/ignis-helpers | @venizia/ignis-helpers |
Production utilities -- Logger, Redis, Queue, Storage, Crypto, Cron, Socket.IO, UID, Network |
| @venizia/dev-configs | @venizia/dev-configs |
Shared ESLint v9, Prettier, and TypeScript configs |
| @venizia/ignis-docs | @venizia/ignis-docs |
VitePress documentation site and MCP server |
Tip
Each package has its own detailed README with API reference, usage examples, and configuration options.
| Tool | Version | Purpose |
|---|---|---|
| Bun | >= 1.3.0 | JavaScript runtime (recommended) |
| Node.js | >= 18.x | Alternative runtime (optional) |
| PostgreSQL | >= 14.x | Database server |
mkdir 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
bun add -d drizzle-kit @types/pg @types/lodashImportant
Both experimentalDecorators and emitDecoratorMetadata must be true in your tsconfig.json. The easiest way is to extend @venizia/dev-configs/tsconfig.common.json.
Create src/index.ts:
import { z } from '@hono/zod-openapi';
import {
BaseApplication,
BaseController,
controller,
get,
HTTP,
IApplicationInfo,
jsonContent,
} from '@venizia/ignis';
import { Context } from 'hono';
// 1. Define a controller
@controller({ path: '/hello' })
class HelloController extends BaseController {
constructor() {
super({ scope: 'HelloController', path: '/hello' });
}
override binding() {}
@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 { name: 'my-app', version: '1.0.0', description: 'My first Ignis app' };
}
staticConfigure() {}
preConfigure() {
this.controller(HelloController);
}
postConfigure() {}
setupMiddlewares() {}
}
// 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 src/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 for interactive Swagger UI documentation.
Tip
See the complete CRUD tutorial and 5-minute quickstart example for a full working API with database, models, repositories, and auto-generated CRUD endpoints.
HTTP Request
GET /api/todos/:id
|
v
+------------------+
| Hono Router | <-- OpenAPIHono with Zod schema validation
+--------+---------+
|
v
+------------------+
| Auth Middleware | <-- JWT/Basic token verification (optional per route)
+--------+---------+
|
v
+------------------+
| Controller | <-- Handles HTTP, validates input, OpenAPI specs
| @get('/...') |
+--------+---------+
|
v
+------------------+
| Service | <-- Business logic (optional layer)
| (optional) |
+--------+---------+
|
v
+------------------+
| Repository | <-- Type-safe data access (find, create, update, delete)
| findById(id) | Mixins: FieldsVisibility, DefaultFilter
+--------+---------+
|
v
+------------------+
| DataSource | <-- Drizzle ORM + node-postgres connection pool
| (singleton) | Schema auto-discovery from @repository bindings
+--------+---------+
|
v
+------------------+
| PostgreSQL |
+------------------+
@controller({ path: '/users' })
export class UserController extends BaseController {
constructor(
@inject({ key: 'services.UserService' }) private userService: UserService,
) {
super({ scope: 'UserController', path: '/users' });
}
}Bindings are namespaced: "controllers.UserController", "services.AuthService", "repositories.UserRepo". The namespace automatically becomes a tag for discovery.
Note
See the Core Concepts documentation for DI flow details, boot sequence, request lifecycle, repository pattern, transaction support, and models with enrichers.
| Phase | Method | What to do |
|---|---|---|
| 1 | staticConfigure() |
Serve static files, pre-DI setup |
| 2 | preConfigure() |
Register controllers, services, components |
| 3 | registerDataSources() |
[AUTOMATIC] Configure all datasources |
| 4 | registerComponents() |
[AUTOMATIC] Configure all components |
| 5 | registerControllers() |
[AUTOMATIC] Mount all controller routes |
| 6 | postConfigure() |
Post-registration hooks, inspection, seeding |
| 7 | setupMiddlewares() |
Register Hono middlewares (CORS, body limit) |
| 8 | start() |
Start HTTP server (Bun or Node) |
| 9 | executePostStartHooks() |
[AUTOMATIC] Run post-start hooks |
Phases 3, 4, 5, and 9 are automatic -- you only need to implement the others.
Register components in preConfigure():
class App extends BaseApplication {
preConfigure() {
this.component(HealthCheckComponent);
this.component(SwaggerComponent);
this.component(AuthenticateComponent);
}
}| Component | What It Provides | Endpoints |
|---|---|---|
| HealthCheckComponent | Health, liveness, and readiness probes | GET /health, /health/live, /health/ready |
| SwaggerComponent | Interactive API documentation (Swagger UI or Scalar UI) | GET /doc/explorer, /doc/openapi.json |
| AuthenticateComponent | JWT + Basic auth strategies, token services, auth middleware | Configurable |
| AuthorizationComponent | Casbin-based RBAC, permission mapping, authorize() middleware |
N/A (middleware) |
| RequestTrackerComponent | x-request-id header injection, request body parsing |
N/A (middleware) |
| StaticAssetComponent | File upload/download CRUD with MinIO, Disk, or Memory backend | Configurable CRUD |
| MailComponent | Email via Nodemailer or Mailgun with Direct, BullMQ, or InternalQueue executors | N/A (service) |
| SocketIOComponent | Socket.IO server with Redis adapter for horizontal scaling | WebSocket |
Tip
See the Core README for detailed component configuration, authentication setup, and ControllerFactory auto-generated CRUD.
The @venizia/ignis-helpers package provides production-ready infrastructure utilities. Each helper extends BaseHelper and follows the same pattern:
| Helper | Import Path | Description |
|---|---|---|
| LoggerFactory | @venizia/ignis-helpers |
Winston-based logger with daily file rotation, UDP transport, and scoped logging |
| RedisHelper | @venizia/ignis-helpers/redis |
Redis Single + Cluster mode, pub/sub with zlib compression |
| QueueHelper (BullMQ) | @venizia/ignis-helpers/bullmq |
Redis-backed job queue with delayed jobs, retries, concurrency |
| QueueHelper (InMem) | @venizia/ignis-helpers/in-mem-queue |
In-memory generator-based queue for development/testing |
| QueueHelper (MQTT) | @venizia/ignis-helpers/mqtt |
MQTT message queue for IoT and lightweight pub/sub |
| QueueHelper (Kafka) | @venizia/ignis-helpers/kafka |
Apache Kafka producer/consumer/admin (experimental) |
| MinioHelper | @venizia/ignis-helpers/minio |
S3-compatible object storage with bucket management |
| DiskHelper | @venizia/ignis-helpers/disk-storage |
Local filesystem storage with common IStorageHelper interface |
| CryptoHelper | @venizia/ignis-helpers/crypto |
AES-256-CBC/GCM encryption, RSA with DER keys, ECDH P-256 |
| UIDHelper | @venizia/ignis-helpers/uid |
Snowflake 70-bit unique IDs, Base62 encoding |
| CronHelper | @venizia/ignis-helpers/cron |
Cron job scheduling with modification and duplication |
| SocketIOHelper | @venizia/ignis-helpers/socket-io |
Socket.IO server with Redis adapter, auth, room management |
| NetworkHelper | @venizia/ignis-helpers/network |
HTTP client, TCP server/client with TLS, UDP with multicast |
| WorkerHelper | @venizia/ignis-helpers/worker |
Thread pool management (max = CPU cores) |
my-ignis-app/
src/
application.ts # Application configuration and lifecycle
index.ts # Entry point
migration.ts # Drizzle migration configuration
controllers/ # HTTP request handlers
services/ # Business logic
repositories/ # Data access layer
models/entities/ # Database models (Drizzle pgTable + BaseEntity)
datasources/ # Database connections
components/ # Reusable modules
.env.development
tsconfig.json
The boot system auto-discovers files by convention:
controllers/*.controller.{ts,js}-> Registered as transient bindingsservices/*.service.{ts,js}-> Registered as transient bindingsrepositories/*.repository.{ts,js}-> Registered as transient bindingsdatasources/*.datasource.{ts,js}-> Registered as singleton bindings
# Build all packages (respects dependency order)
make build
# Build specific package (includes all dependencies)
make core # Builds dev-configs -> inversion -> helpers -> boot -> core
make boot # Builds dev-configs -> inversion -> helpers -> boot
# Clean all build artifacts
make clean
# Lint
make lint # Lint all packages
make lint-all # Lint packages and examples
# Test (from package directory)
cd packages/core && bun test
# Build individual package
cd packages/core && bun run rebuild| Target | Description |
|---|---|
make build |
Rebuild all packages in dependency order |
make install |
Install all dependencies with bun |
make clean |
Clean build artifacts from all packages |
make core |
Rebuild @venizia/ignis (and all dependencies) |
make lint |
Lint all packages |
make lint-all |
Lint packages and examples |
The examples/ directory contains reference implementations:
| Example | Description | Complexity |
|---|---|---|
| 5-mins-qs | Minimal single-file quickstart -- hello world | Beginner |
| vert | Production-ready reference with full CRUD, auth, components, transactions, multiple models with relations | Advanced |
| rpc-api-server | RPC-style API server | Intermediate |
| rpc-client-app | React 19 + Vite + Ant Design frontend consuming RPC API | Frontend |
| socket-io-test | Socket.IO real-time integration example | Intermediate |
| websocket-test | Native WebSocket integration example | Intermediate |
cd examples/vert
# Copy environment template
cp .env.example .env.development
# Edit .env.development with your PostgreSQL credentials
# Install and run
bun install
bun run migrate:dev # Push schema to database
bun run server:dev # Start development serverYes. Bun is the primary runtime and provides the best performance, but Ignis supports Node.js >= 18 as a secondary runtime. The framework detects the runtime automatically and uses @hono/node-server when running on Node.js instead of Bun.serve. Some helpers (like Bun-native WebSocket) are Bun-specific, but the core framework, controllers, repositories, and components all work on Node.js.
Drizzle ORM supports MySQL and SQLite, but Ignis repositories are built around pgTable (PostgreSQL table definitions). The where operators, filter builders, and query generation assume PostgreSQL semantics. Using MySQL or SQLite would require building custom repository implementations.
| Aspect | LoopBack 4 | Ignis |
|---|---|---|
| Performance | ~15-20k req/s | ~140k req/s |
| HTTP Engine | Express | Hono |
| ORM | Juggler (custom) | Drizzle (type-safe SQL) |
| Maintenance | Abandoned (IBM) | Actively developed |
| IoC Container | ~2000 lines, complex | ~350 lines, simple |
| Runtime | Node.js only | Bun primary, Node.js secondary |
Ignis is at version 0.x, which means the API may have breaking changes between minor versions. However, it is used internally in production at VENIZIA AI. The core patterns (controllers, repositories, DI, components) are stable. We recommend pinning exact versions and testing thoroughly before upgrading.
Tip
See the full documentation for more FAQs covering middleware, relations, route patterns, and deployment.
Online Documentation: https://venizia-ai.github.io/ignis
The documentation covers getting started, core concepts (application lifecycle, controllers, DI, repositories, components), best practices (architecture, security, performance), API references, and deployment guides.
Key links: Philosophy • 5-Minute Quickstart • Building a CRUD API • Core Concepts • Best Practices
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
# Build all packages
make build
# Run documentation locally
bun run docs:dev- Conventional Commits:
feat:,fix:,docs:,chore:,refactor:,test: - Branch naming:
feature/*,fix/*,docs/*,chore/* - PRs target
develop-- nevermaindirectly - Options objects:
fn({ key, value })notfn(key, value) - Package manager: Bun only -- never npm, yarn, or pnpm
- Build tool:
tscdirectly -- nevernpx,bunx, orbun x
This project is licensed under the MIT License -- see the LICENSE.md file for details.
Ignis is inspired by:
- LoopBack 4 -- Enterprise patterns, decorator-based DI, repository pattern, component system
- Hono -- Performance, modern API design, multi-runtime support
- Drizzle ORM -- Type-safe SQL, schema-first approach
- NestJS -- Module system concepts, decorator patterns
- Spring Boot -- IoC/DI container design, auto-configuration patterns
- Documentation: https://venizia-ai.github.io/ignis
- GitHub Issues: https://github.com/VENIZIA-AI/ignis/issues
- Author: VENIZIA AI Developer developer@venizia.ai