Build Hono APIs.
Nooh compiles the rest.

File-based routing, type-safe composition,dependency injection, middleware and typed errors —compiled into native Hono.

src/routes/users/[id].get.ts
↓
NoohNOOH
↓
Hono
app.get('/users/:id', ...)
COMPILE-TIME·TYPE-SAFE·ZERO DEPENDENCY·BUILT ON Hono
THE CORE IDEA

Your filesystem is your router.

Your route structure is derived from the filesystem and compiled into normal Hono routes. Nooh reads your files, analyzes your types and generates a Hono app at build time.

Filesystem
src/
└─routes/
├─index.get.ts
└─users/
├─index.get.ts
├─[id].get.ts
└─$.ts
Nooh logoNooh Compiler
✓Parse files
✓Infer types
✓Build routes
✓Generate Hono app
Hono Routes
GET/
GET/users
GET/users/:id
...
DEPENDENCY INJECTION

Type-safe dependency injection built-in.

Declare your dependencies in modular containers and inject them directly into route handlers. Context properties are automatically typed with static error detection for duplicates and invalid references.

DEPENDENCY CONTAINERsrc/deps/db.ts
import { container } from "nooh";
import { UsersRepository } from "...";

export const db = container({
  users: () => new UsersRepository(),
});
ROUTE HANDLERsrc/routes/users/[id].post.ts
import { post } from "@router/users/[id]";
import { db } from "@deps/db";

export default post({
  deps: [db.users],
  handler: async ({ c, users }) => {
    const user = await users.getById(c.req.param("id"));

    return c.json(user);
  },
});

Auto-typed Context

Injected dependencies likeusersare automatically typed on the handler argument.

Production Safety

Detects duplicate dependencies, invalid references, and unhandled errors at compile time.

Zero Runtime Overhead

Dependencies are resolved during build time into standard Hono application code.

TYPED ERROR HANDLING

Declarative, fully-typed error helpers.

Declare any class extendingErrorin your route signature. Error factories are automatically bound to the handler context with full parameter inference and minimal runtime cost.

CUSTOM ERRORSsrc/errors/user.ts
export class UserNotFound extends Error {
  constructor(public userId: string) {
    super(`User ${userId} not found`);
  }
}

export class UnauthorizedAccess extends Error {
  constructor() {
    super("Unauthorized access");
  }
}
ROUTE HANDLERsrc/routes/users/[id].get.ts
import { get } from "@router/users/[id]";

import { db } from "@deps/db";
import { UserNotFound, UnauthorizedAccess } from "@errors/user";

export default get({
  deps: [db.users],
  errors: {
    notFound: UserNotFound,
    unauthorized: UnauthorizedAccess,
  },
  handler: async ({ c, users, errors }) => {
    const id = c.req.param("id");
    const user = await users.getById(id);

    // strongly typed error factory
    if (!user) throw errors.notFound(id);
    
    return c.json(user);
  },
});

Typed Error Factory

Declared errors map directly toerrors.<key>()helpers with inferred constructor parameters.

Standard Error Support

Use any class extendingErrorwith full custom constructor arguments support.

Minimal Runtime Cost

Compiles directly into optimized standard logic without additional runtime abstraction overhead.

INPUT VALIDATION

First-class Standard Schema validation.

Define request validation in thevalidationobject using any Standard Schema library (Zod, Valibot, ArkType). Nooh compiles it with@hono/standard-validatorby default, or your choice of custom validator.

SCHEMA VALIDATIONsrc/routes/users.post.ts
import { post } from "@router/users";
import { z } from "zod";

const createUserSchema = z.object({
  name: z.string().min(2),
  email: z.string().email(),
});

export default post({
  validation: {
    json: createUserSchema,
  },
  handler: async ({ c }) => {
    // validated payload is automatically typed
    const data = c.req.valid("json");

    return c.json({ user: data }, 201);
  },
});
CUSTOMIZABLE ENGINEnooh.config.ts
import { config } from "@nooh-ts/nooh";
import { zValidator } from '@hono/zod-validator'

export default config({
  // Optional: swap default @hono/standard-validator
  // with any custom or Hono-supported validator
  validator: {
    engine: zValidator,
  },
});

Standard Schema Compliant

Works seamlessly with Zod, Valibot, ArkType, or any library implementing the Standard Schema specification.

All Hono Request Targets

Validatejson,query,param,header, orform.

Pluggable Engine

Easily swap the default validator engine for any other Hono validator or custom validation logic.

COMPOSEABLE MIDDLEWARE

Scoped route & group middleware.

Create type-safe middleware with the@router/middlewarehelper. Apply them per route or cascade them across entire route subtrees with$.tsgroup files.

GROUP MIDDLEWAREsrc/routes/users/$.ts
import logger from "@middleware/logger";
import { group } from "@nooh-ts/nooh";

// applies to all routes under /users/*
export default group({
  middleware: [logger],
});
MIDDLEWARE DEFINITIONsrc/middleware/logger.ts
import { middleware } from "@router/middleware";

export default middleware(async (c, next) => {
  const start = Date.now();

  await next();

  const duration = Date.now() - start;
  console.log(`${c.req.method} ${c.req.path} ${c.res.status} ${duration}ms`);
});

File-System Grouping

$.tsfiles represent route groups, easily scoping middleware across entire subtrees.

Type-Safe Context

Standard Hono contextcandnext()functions with full type inference and environment bindings.

Cascading Execution

Group middleware executes before route-level middleware, providing predictable, hierarchical pipeline execution.

IT COMPILES AWAY

Write Nooh. Ship Hono.

Nooh uses your routes, dependencies, middleware and errors as compile-time composition. The generated application is ordinary Hono code with no Nooh runtime.

WHAT YOU WRITEsrc/routes/users/[id].post.ts
import { post } from "@router/users/[id]";

import { db } from "@deps/db";
import { UserNotFound } from "@errors";
import logger from "@middleware/logger";

export default post({
  deps: [db.users],
  errors: { notFound: UserNotFound },
  middleware: [logger],

  handler: async ({ users, error, c }) => {
    const user = await users.getById(c.req.param("id"));

    if (!user) {
      throw error.notFound();
    }

    return c.json(user);
  },
});
Nooh logoNOOHCompile time→static composition
GENERATED HONO .nooh/*
// Conceptual generated output

import { Hono } from "hono";
import type { App } from "./types.js";

import { UsersRepository } from "../src/deps/db.js";
import UserNotFound from "../src/errors/UserNotFound.js";
import logger from "../src/middleware/logger.js";

const users = new UsersRepository();

const app = new Hono<App>();

app.post("/users/:id", logger, async (c) => {
  const user = await users.getById(
    c.req.param("id")
  );

  if (!user) {
    throw new UserNotFound();
  }

  return c.json(user);
});

export default app;
.nooh/router/*→.nooh/groups/*→.nooh/app.ts
100% HONO COMPATIBLE

Runs anywhere Hono runs.

Nooh compiles into native Hono applications. You get 100% compatibility with the entire Hono ecosystem, official middleware, and any JavaScript runtime out of the box.

Node.js
Bun
Deno
Cloudflare Workers
Vercel / AWS Lambda

Universal Runtimes

Deploy your API on any JavaScript runtime or edge infrastructure without modifying a single line of application logic.

Full Hono Ecosystem

Use any existing Hono middleware, official packages, or third-party community extensions seamlessly.

Zero Lock-in

Hono is the entrypoint. Your project compiles to readable standard TypeScript that you own completely.

BUILT FOR DEVELOPERS

Modern TypeScript ergonomics.
Production ready Hono output.

Nooh gives you the structure and developer experience of a modern framework, with the performance and simplicity of Hono — and it disappears after compilation.

Type-safe

Full TypeScript support, from routes to context and errors.

Modular

Composed dependencies, middleware and logic.

File-based

Your filesystem defines your API surface.

Simple

No complex config. No magic.

Composable

Dependency injection, middleware and logic.

Fast

Zero runtime overhead. Just Hono.

BUILT FOR REAL PROJECTS

A clean developer experience.
From idea to production.

bash
# Create a new project
pnpm create @nooh-ts/template
cd my-app
# Install dependencies
pnpm install
# Develop
pnpm dev
✓Zero config

Just start coding.

✓Tree-shakeable

Only what you use.

✓Works anywhere

Node.js 18+, Bun, Deno, Serverless, etc.

Nooh logo

Open source and community driven.

Nooh is free, open source and built for the community.

View on GitHub
GitHub
3+★
Contributors
2+contributors