v4.11.0

honojs/honov4.11.0Dec 13, 2025by yusukebe

AI Summary

Hono v4.11.0 introduces significant type system improvements including a fix for middleware pathless handlers, typed URLs for the Hono client, and custom NotFoundResponse type support. This release also adds a tryGetContext helper for context storage and a buildSearchParams option for custom query serialization.

Key Highlights

  • Fixed type system bug where app did not have correct type with pathless handlers
  • Added typed URL support for Hono client - pass base URL as second type parameter to hc for precise URL types
  • Custom NotFoundResponse type support via module augmentation for typed 404 responses
  • New tryGetContext helper in Context Storage middleware returns undefined instead of throwing
  • Added buildSearchParams option to customize query parameter serialization

New Features

  • Typed URL for Hono client - $url returns exact URL type with protocol, host, and path information
  • Custom NotFoundResponse type via module augmentation for typed notFound() responses
  • tryGetContext helper in context-storage middleware for safer context retrieval
  • buildSearchParams option to customize query parameter serialization
  • wrapTime addition to timing middleware for simplified usage
  • force option support for pretty-json middleware
  • CSP report-to and report-uri directive support in secure-headers middleware
  • Type system fix replacing schema-based path tracking with CurrentPath parameter

Full Release Notes

# Release Notes

Hono v4.11.0 is now available!

This release includes new features for the Hono client, middleware improvements, and an important type system fix.

## Type System Fix for Middleware

We've fixed a bug in the type system for middleware. Previously, `app` did not have the correct type with pathless handlers:

```ts
const app = new Hono()
  .use(async (c, next) => {
    await next()
  })
  .get('/a', async (c, next) => {
    await next()
  })
  .get((c) => {
    return c.text('Hello')
  })

// app's type was incorrect
```

This has now been fixed.

Thanks @kosei28!

## Typed URL for Hono Client

You can now pass the base URL as the second type parameter to `hc` to get more precise URL types:

```ts
const client = hc<typeof app, 'http://localhost:8787'>(
  'http://localhost:8787/'
)

const url = client.api.posts.$url()
// url is TypedURL with precise type information
// including protocol, host, and path
```

This is useful when you want to use the URL as a type-safe key for libraries like SWR.

Thanks @miyaji255!

## Custom NotFoundResponse Type

You can now customize the `NotFoundResponse` type using module augmentation. This allows `c.notFound()` to return a typed response:

```ts
import { Hono, TypedResponse } from 'hono'

declare module 'hono' {
  interface NotFoundResponse
    extends Response,
      TypedResponse<{ error: string }, 404, 'json'> {}
}

const app = new Hono()
  .get('/posts/:id', async (c) => {
    const post = await getPost(c.req.param('id'))
    if (!post) {
      return c.notFound()
    }
    return c.json({ post }, 200)
  })
  .notFound((c) => c.json({ error: 'not found' }, 404))
```

Now the client can correctly infer the 404 response type.

Thanks @miyaji255!

## tryGetContext Helper

The new `tryGetContext()` helper in the Context Storage middleware returns `undefined` instead of throwing an error when the context is not available:

```ts
import { tryGetContext } from 'hono/context-storage'

const context = tryGetContext<Env>()
if (context) {
  // Context is available
  console.log(context.var.message)
}
```

Thanks @AyushCoder9!

## Custom Query Serializer

You can now customize how query parameters are serialized using the `buildSearchParams` option:

```ts
const client = hc<AppType>('http://localhost', {
  buildSearchParams: (query) => {
    const searchParams = new URLSearchParams()
    for (const [k, v] of Object.entries(query)) {
      if (v === undefined) continue
      if (Array.isArray(v)) {
        v.forEach((item) => searchParams.append(`${k}[]`, item))
      } else {
        searchParams.set(k, v)
      }
    }
    return searchParams
  },
})
```

Thanks @bolasblack!

## New features

- feat(types): make Hono client's $url return the exact URL type https://github.com/honojs/hono/pull/4502
- feat(types): enhance NotFoundHandler to support custom NotFoundResponse type https://github.com/honojs/hono/pull/4518
- feat(timing): add wrapTime to simplify usage https://github.com/honojs/hono/pull/4519
- feat(pretty-json): support force option https://github.com/honojs/hono/pull/4531
- feat(client): add buildSearchParams option to customize query serialization https://github.com/honojs/hono/pull/4535
- feat(context-storage): add optional tryGetContext helper https://github.com/honojs/hono/pull/4539
- feat(secure-headers): add CSP report-to and report-uri directive support https://github.com/honojs/hono/pull/4555
- fix(types): replace schema-based path tracking with CurrentPath parameter https://github.com/honojs/hono/pull/4552

## All changes

* chore: update esbuild to version 0.27.1 by @kosei28 in https://github.com/honojs/hono/pull/4571
* fix(hono/jsx): display blank when children is nullish by @techfish-11 in https://github.com/honojs/hono/pull/4573
* feat(types): make Hono client's $url return the exact URL type by @miyaji255 in https://github.com/honojs/hono/pull/4502
* feat(types): enhance NotFoundHandler to support custom NotFoundResponse type by @miyaji255 in https://github.com/honojs/hono/pull/4518
* feat(timing): add wrapTime to simplify usage by @PassiDel in https://github.com/honojs/hono/pull/4519
* feat(pretty-json): support force option by @missinglink in https://github.com/honojs/hono/pull/4531
* feat(context-storage): Add optional tryGetContext helper to context-storage middleware by @AyushCoder9 in https://github.com/honojs/hono/pull/4539
* feat(client): add buildSearchParams option to customize query serialization by @bolasblack in https://github.com/honojs/hono/pull/4535
* feat(secure-headers): Add CSP report-to and report-uri directive support by @cruzz77 in https://github.com/honojs/hono/pull/4555
* fix(types): replace schema-based path tracking with CurrentPath parameter by @kosei28 in https://github.com/honojs/hono/pull/4552
* Next by @yusukebe in https://github.com/honojs/hono/pull/4574

## New Contributors
* @missinglink made their first contribution in https://github.com/honojs/hono/pull/4531
* @bolasblack made their first contribution in https://github.com/honojs/hono/pull/4535
* @cruzz77 made their first contribution in https://github.com/honojs/hono/pull/4555

**Full Changelog**: https://github.com/honojs/hono/compare/v4.10.8...v4.11.0