Getting Started
Core Concepts
Built-In Middleware
Advanced Features
Troubleshooting
Hono provides a lightweight, high-performance JSX engine designed to work seamlessly with web standards. It allows you to build HTML components using JSX syntax and render them directly within your Hono application, supporting both standard string-based responses and efficient streaming.
The jsxRenderer middleware is the primary way to define a global layout for your pages. Once configured, it attaches a .render() method to your response context (c), allowing you to inject content into your layouts easily.
jsxRenderer middleware to wrap your content in a consistent HTML structure.c.render() within your route handlers to pass content into the layout.import { Hono } from 'hono'
import { jsxRenderer } from 'hono/jsx-renderer'
const app = new Hono()
app.get(
'/page/*',
jsxRenderer(({ children }) => {
return (
<html>
<body>
<header>My Website Header</header>
<main>{children}</main>
</body>
</html>
)
})
)
app.get('/page/about', (c) => {
return c.render(<h1>About Me</h1>)
})Tip
Use the jsxRenderer at the top level or group it via route paths (like /page/* above) to apply common styles, headers, and footer layouts to multiple routes simultaneously.
Sometimes your components need data from the current request (like parameters, headers, or URL information). Hono provides a useRequestContext hook for this purpose.
import { useRequestContext } from 'hono/jsx-renderer'
const PageInfo = () => {
const c = useRequestContext()
return <p>Requested URL: {c.req.url}</p>
}Warning
The useRequestContext hook will throw an error if called outside of a request scope, such as during server startup or in components not rendered via the jsxRenderer.
For large pages or heavy content, you can enable streaming to send HTML to the client in chunks. This improves the "Time to First Byte" (TTFB) significantly.
You can configure streaming via the jsxRenderer options:
app.get(
'/stream',
jsxRenderer(
({ children }) => <html>{children}</html>,
{ stream: true }
),
(c) => c.render(<div>This is streamed!</div>)
)Note
When stream is enabled, Hono automatically sets appropriate HTTP headers like Transfer-Encoding: chunked.
<html>, <head>, <body>), which accepts children as a property to inject dynamic content.