Hono (hi, η«, fire; the frameworkβs name plays on η, flame) and Tsuki (tsuki, ζ, moon) mirror each other: η« β ζ β a fast, fiery edge runtime with a calm, reflective layer on top. Hono stays lean at HTTP; Tsuki adds modules, decorators, and DI without dulling that core.
Tsuki borrows proven ideas from the NestJS ecosystem so teams can reuse familiar mental models without committing to a full Nest stack on Hono:
- Modules & controllers β
@Module,@Controller, and route decorators for structure and discovery. - Dependency injection β constructor injection via tsyringe, with singleton providers and explicit registration.
- Cross-cutting concerns β guards, pipes, interceptors, exception filters, and middleware hooks arranged in a predictable request pipeline.
- Metadata-driven behavior β decorators carry OpenAPI and routing hints, similar to Nestβs decorator-first configuration style.
NestJS remains the reference for many of these patterns; Tsuki adapts them for Hono-first apps that want the same ergonomics in a smaller footprint.
| Package | Description |
|---|---|
@tsuki-hono/common |
Decorators, interfaces, exceptions, pipes, logger, and request context |
@tsuki-hono/core |
Application runtime, DI container utils, route registration |
@tsuki-hono/event-emitter |
Redis pub/sub event system with @OnEvent / @EmitEvent |
@tsuki-hono/openapi |
OpenAPI 3.1 document generation from decorator metadata |
Projects that ship on this stack:
- Afilmory β a personal photography site with a nostalgic, film-inspired presentation layer and a Tsuki/Hono backend.
# Clone the repository
git clone https://github.com/innei/tsuki.git
cd tsuki
# Install dependencies
pnpm install
# Run tests
pnpm testimport 'reflect-metadata';
import { serve } from '@hono/node-server';
import { Module, Controller, Get } from '@tsuki-hono/common';
import { createApplication } from '@tsuki-hono/core';
@Controller('hello')
class HelloController {
@Get('/')
greet() {
return { message: 'Hello from Tsuki!' };
}
}
@Module({ controllers: [HelloController] })
class AppModule {}
async function bootstrap() {
const app = await createApplication(AppModule);
serve({ fetch: app.getInstance().fetch, port: 3000 });
}
bootstrap();See individual package READMEs for detailed documentation.
Automated tools work best when they share the same constraints as the framework. LLM.txt is the repoβs agent-oriented guide: package graph, request pipeline, bootstrap steps, DI and TypeScript rules that are easy to get wrong, and how to run tests and typecheck before claiming a change is done. Point your coding agent at that file (or paste it into context) when implementing features in Tsuki or when building an app on @tsuki-hono/*.
Claude Code users also have CLAUDE.md at the repo root with overlapping maintainer-focused notes.
- Package Manager: pnpm 10.x
- Language: TypeScript (ESNext)
- Test: Vitest
pnpm install # Install all dependencies
pnpm test # Run all tests across packagesMIT