夯HumGuides
Back to home

Hono and Hum middleware

Explicitly mount Hum’s file routes onto the Hono app created in app.ts. Both middleware systems run in the same request pipeline, but their scopes are different.

Hono middleware: app and URL scope

Register Hono middleware on the app before Hum is mounted. It runs for matching Hono API routes and Hum requests; a path pattern lets you select which requests it wraps. For example, app-wide middleware can provide shared headers or logging, while an API prefix can be protected independently of pages. This is that file for this site—every response you have loaded carries its x-powered-by header, including the /api/health endpoint it also declares.

TypeScript
// app.ts — the Hono app this documentation runs on
import { Hono } from "hono";
import { createPageService, mountHum } from "@humjs/core";
import { config } from "virtual:hum/build";

const app = new Hono();

app.use("*", async (c, next) => {
  c.header("x-powered-by", "Hum + Hono");
  await next();
});

app.get("/api/health", (c) => c.json({ status: "ok" }));

const pages = createPageService();
await mountHum(app, { ...config, pages });
export default app;

Hum middleware: a directory-scoped mount point

A Hum _middleware.ts is a mount point for a Hono middleware, scoped by the directory it lives in: it applies to Hum file routes in that directory and descendants. Parent middleware is inherited, and the chain runs from the routes root toward the matched route. It also wraps that route’s handlers and the _404 render for unmatched paths under the same directory, but it does not apply to Hono API routes declared in app.ts.

TypeScript
// routes/admin/_middleware.ts
import { define } from "@humjs/core";

// The default export is a Hono middleware. The directory this file lives in
// decides which Hum routes it wraps.
export default define.middleware(async (c, next) => {
  if (!(await isSignedIn(c))) return c.redirect("/login");
  await next();
});

This site has none, so the difference is easy to see: the header above is added by Hono middleware and appears on every response, while a _middleware.ts in routes/docs/ would only run for the guide pages below it—never for /api/health.

Reach for app.use() in app.ts first: it is the general alternative and covers both Hum pages and Hono API routes by path pattern. Use _middleware.ts only when the policy belongs to a branch of Hum’s route tree—for example a URL-transparent (group)/ directory, which a path pattern cannot express. A request matching both passes through Hono middleware first, then the Hum route middleware. Either can short-circuit by returning a Response.