Meet HonoJS: The Future of JavaScript Frameworks!
Daniel Hayes
Full-Stack Engineer · Leapcell

In-depth Understanding of the JavaScript Runtime Framework - Hono
On Github, the JavaScript runtime framework Hono has already received 22k Stars!
The Birth Background of Hono
The birth of Hono can be traced back to December 2021. Its author, as an employee of Cloudflare, hoped to create applications for Cloudflare Workers at that time. However, without using a framework, the code would be very verbose, and there was no framework that met the requirements. Itty-router was good but too simple; Worktop and Sunder did things in line with the author's ideas, but their APIs didn't suit the author's taste. In addition, the author was interested in routers based on the Trie tree structure because of their extremely fast speed. So, the author began to build a Web framework with Trie tree routing.
Extremely Fast Speed
Hono's router, RegExpRouter, is one of the fastest routers currently. It avoids the use of linear loops and has extremely powerful performance. The following is a comparison of the performance of Hono in Cloudflare Workers:
- Hono: 402,820 ops/sec ±4.78% (80 runs sampled)
- itty-router: 212,598 ops/sec ±3.11% (87 runs sampled)
- sunder: 297,036 ops/sec ±4.76% (77 runs sampled)
- worktop: 197,345 ops/sec ±2.40% (88 runs sampled)
It can be seen that Hono is the fastest, and the entire test was completed within 28.06 seconds.
Who is Using Hono?
Hono is a simple Web application framework similar to Express, which can be used to build richer applications. Combined with middleware, Hono can achieve various usage scenarios:
- Building Web APIs
- Proxy for backend servers
- CDN front-end
- Edge applications
- Basic server for libraries
- Full-stack applications
Currently, Hono has been used by many developers and companies. For example, Unkey used Hono's OpenAPI function to deploy applications to Cloudflare Workers. Some of the companies using Hono are as follows:
- Cloudflare
- Nodecraft
- OpenStatus
- Unkey
- Goens
- NOT A HOTEL
- CyberAgent
- AI shift
- Hanabi.rest
- BaseAI
- Leapcell
In addition, large Web services or libraries such as Prisma, Resend, Vercel AI SDK, Supabase, and Upstash also use Hono in their examples. Some developers even use Hono as an alternative to Express.
Hono and Cloudflare are a Perfect Match
The combination of Hono and Cloudflare can bring an excellent experience to developers. Many websites (including Cloudflare documents) show the following "native" JavaScript code as the Cloudflare Workers "Hello World":
export default { fetch: () => { return new Response('Leapcell:Hello World!') } }
Although this helps to understand the principle of Workers, if you want to create an interface that returns a JSON response (such as a GET request for the /books
request), you need to write the following code:
export default { fetch: (req) => { const url = new URL(req.url) if (req.method === 'GET' && url.pathname === '/req') { return Response.json({ ok: true }) } return Response.json( { ok: false }, { status: 404 } ) } }
When using Hono, the code can be simplified to:
import { Hono } from 'hono' const app = new Hono() app.get('/books', (c) => { return c.json({ ok: true }) }) export default app
The code is not only concise but also makes it intuitive to understand that it handles the GET request for /books
. If you need to handle a GET request to /authors/yusuke
and extract the variable leapcell
(the leapcell
can be variable) from the path, the native JavaScript code is as follows:
if (req.method === 'GET') { const match = url.pathname.match(/^\/authors\/([^\/]+)/) if (match) { const author = match[1] return Response.json({ Author: author }) } }
When using Hono, there is no need to write an if
statement. You just need to add an interface definition, and there is no need to write a regular expression to obtain the variable leapcell
. Instead, use the c.req.param()
function:
app.get('/authors/:name', (c) => { const author = c.req.param('name') return c.json({ Author: author }) })
When the number of routes increases, the code maintenance will become complicated. When using Hono, the code is concise and easy to maintain.
On-demand Import Functionality
Hono is very small. Using the smallest preset hono/tiny
, you can write a "Hello World" program within 12 KB. This is because it only uses the Web standard APIs built into the runtime and minimizes its functions. In contrast, the packaged size of Express is 579 KB.
Even so, Hono can still achieve many functions. For example, implementing basic authentication is a bit troublesome, but Hono has a built-in basic authentication middleware. You can apply basic authentication to the /auth/page
path in the following way:
import { Hono } from 'hono' import { basicAuth } from 'hono/basic-auth' const app = new Hono() app.use( '/auth/*', basicAuth({ username: 'hono', password: 'acoolproject', }) ) app.get('/auth/page', (c) => { return c.text('You are authorized') })
The Hono package includes built-in middleware that also supports Bearer and JWT authentication, as well as simple configuration of CORS. These built-in middleware do not rely on external libraries. At the same time, many third-party middleware can also be used (allowing the use of external libraries), such as middleware for authentication using Clerk and Auth.js, and middleware for validation using Zod and Valibot.
Hono also provides some built-in tools, such as the Streaming helper, which is useful for implementing AI functions. These tools can be added on demand, and the file size will only increase when they are added. In Cloudflare Workers, there is a certain limit to the file size of a Worker. Keeping the core small and expanding functionality through middleware and helpers is a very reasonable approach.
The following are some of the middleware and helper tools that Hono has, which can greatly improve development efficiency:
- Basic Authentication
- Bearer Authentication
- Body Limit
- Cache
- Compress
- Context Storage
- Cookie
- CORS
- ETag
- html
- JSX
- JWT Authentication
- Logger
- Pretty JSON
- Secure Headers
- SSG
- Streaming
- GraphQL Server
- Firebase Authentication
- Sentry, etc.
Custom Middleware
An important concept in Hono is "handlers" and "middleware". A handler is a user-defined function used to receive requests and return responses. For example, you can write a handler that gets the value of a query parameter, retrieves data from a database, and returns the result in JSON format. Middleware can handle requests that reach the handler and responses returned by the handler. You can combine middleware to build larger and more complex applications, and its structure is similar to an onion.
Creating middleware is very concise. For example, a custom logger that records request logs can be written like this:
app.use(async (c, next) => { console.log(`[${c.req.method}] ${c.req.path}`) await next() })
If you want to add a custom header to the response, you can write it like this:
app.use(async (c, next) => { await next() c.header('X - Message', 'Hi, this is Hono!') })
It will be interesting to combine it with HTMLRewriter. If an interface returns HTML, you can write middleware that modifies HTML tags, as shown below:
app.get('/pages/*', async (c, next) => { await next() class AttributeRewriter { constructor(attributeName) { this.attributeName = attributeName } element(element) { const attribute = element.getAttribute(this.attributeName) if (attribute) { element.setAttribute(this.attributeName, attribute.replace('oldhost', 'newhost')) } } } const rewriter = new HTMLRewriter().on('a', new AttributeRewriter('href')) const contentType = c.res.headers.get('Content - Type') if (contentType!.startsWith('text/html')) { c.res = rewriter.transform(c.res) } })
Creating middleware only requires working with the context, and there is very little to remember.
RPC Calls
Hono has a powerful type system, and one of its features is RPC (Remote Procedure Call). Through RPC, you can use TypeScript types to express the server-side API specification. When these types are loaded as generics on the client side, the path, parameters, and return types of each API endpoint will be inferred.
For example, suppose there is an endpoint for creating a blog post, which accepts an id
of type number
and a title
of type string
. Using Zod (a validation library that supports TypeScript inference), you can define the following schema:
import { z } from 'zod' const schema = z.object({ id: z.number(), title: z.string() })
Create a handler that receives this object via a POST request in JSON format and uses the Zod Validator to check if it matches the schema. The response will have a property of type string named message
:
import { zValidator } from '@hono/zod - validator' const app = new Hono().basePath('/v1') // ... const routes = app.post('/posts', zValidator('json', schema), (c) => { const data = c.req.valid('json') return c.json({ message: `${data.id.toString()} is ${data.title}` }) })
This is a "typical" Hono handler, and the routes
type obtained through typeof
will contain information about its Web API specification. In this example, it includes the endpoint for creating a blog post — sending a POST request to /posts
will return a JSON object.
export type AppType = typeof routes
Now create a client and pass the previous AppType
as a generic to the Hono client object:
import { hc } from 'hono/client' import { AppType } from '.' const client = hc<AppType>('http://localhost:8787')
After the setup is complete, the code completion function will work perfectly. When writing client code, there is no need to fully understand the API specification, which helps to eliminate errors.
Server-side JSX
Hono provides built-in JSX, which is a syntax that allows you to write code similar to HTML tags in JavaScript. When it comes to JSX, you may first think of React (a front-end UI library). But Hono's JSX was originally developed to run only on the server side. The author of Hono was looking for a template engine for rendering HTML during the initial development. Most template engines (such as Handlebars and EJS) use eval
internally, and eval
is not supported on Cloudflare Workers, so the author thought of using JSX.
The uniqueness of Hono's JSX lies in treating tags as strings. Therefore, the following code is feasible:
console.log((<h1>Hello!</h1>).toString())
There is no need to call renderToString()
as in React. If you want to render HTML, you just need to return this string:
app.get('/', (c) => c.html(<h1>Hello</h1>))
Interestingly, you can create Suspense (a feature in React that allows showing a fallback UI while waiting for an asynchronous component to load), and there is no need for any client-side implementation. The asynchronous component runs in a server-only implementation.
Server-side JSX is more interesting than expected. You can reuse Hono's JSX in the same way as the JSX toolchain of React, including the function of completing tags in the editor, bringing mature front-end technologies to the server side.
Writing Tests
Testing is crucial. It is easy to write tests using Hono. For example, to write a test for an interface, testing that a GET request to /
returns a status code of 200, the code is as follows:
it('should return 200 response', async () => { const res = await app.request('/') expect(res.status).toBe(200) })
The advantage of this kind of test is that there is no need to start a server, and the Web standard API black-boxes the server layer. Hono's internal test code has 20,000 lines, but most of them are written like the above code, without the need to start a server.
Moving Towards Full-stack
Hono released a new major version 4.7 in February 2025, with three prominent major features:
- Static Site Generation
- Client Components
- File-based Routing
Through these features, you can create full-stack applications with user interfaces in Hono. The introduction of client components supports JSX working on the client side, which can add interactivity to the page; Static Site Generation allows you to create blogs, etc., without packaging them into a single JavaScript file.
Leapcell: The Next-Gen Serverless Platform for Web Hosting
Finally, I recommend the most suitable platform for deploying Node services: Leapcell
1. Multi-Language Support
- Develop with JavaScript, Python, Go, or Rust.
2. Deploy unlimited projects for free
- pay only for usage — no requests, no charges.
3. Unbeatable Cost Efficiency
- Pay-as-you-go with no idle charges.
- Example: $25 supports 6.94M requests at a 60ms average response time.
4. Streamlined Developer Experience
- Intuitive UI for effortless setup.
- Fully automated CI/CD pipelines and GitOps integration.
- Real-time metrics and logging for actionable insights.
5. Effortless Scalability and High Performance
- Auto-scaling to handle high concurrency with ease.
- Zero operational overhead — just focus on building.
Explore more in the documentation!
Leapcell Twitter: https://x.com/LeapcellHQ