---
title: "JSX Components and Context"
description: "Hono's JSX implementation bridges server-side rendering, streaming, and client DOM interaction JSX Runtime, Client DOM and Hooks, JSX Streaming and Suspense. It provides robust APIs for component h..."
last_updated: "2026-10-12T08:14:12.740617+00:00"
canonical_url: "https://www.doc0.dev/docs/552ca36e-f67e-41c3-a07a-def9bd9551b0/technical/jsx-and-ui/jsx-components-and-context"
---

<details>
<summary>Relevant source files</summary>

The following files were used as context for generating this wiki page:

- [src/middleware/jsx-renderer/index.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/jsx-renderer/index.ts)
- [src/jsx/dom/intrinsic-element/components.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/dom/intrinsic-element/components.ts)
- [src/jsx/intrinsic-element/components.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/intrinsic-element/components.ts)
- [src/jsx/components.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/components.ts)
- [src/jsx/dom/render.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/dom/render.ts)
- [src/jsx/base.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/base.ts)
- [src/jsx/context.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/context.ts)
- [src/jsx/jsx-runtime.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/jsx-runtime.ts)
- [src/jsx/streaming.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/streaming.ts)
- [src/jsx/hooks/index.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/hooks/index.ts)
- [src/jsx/intrinsic-elements.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/intrinsic-elements.ts)
- [src/jsx/dom/jsx-dev-runtime.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/dom/jsx-dev-runtime.ts)
- [src/jsx/jsx-dev-runtime.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/jsx-dev-runtime.ts)
- [src/context.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/context.ts)
- [src/jsx/dom/context.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/dom/context.ts)
- [src/jsx/dom/hooks/index.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/dom/hooks/index.ts)
- [src/jsx/dom/components.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/dom/components.ts)
- [src/jsx/index.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/index.ts)
- [src/jsx/dom/index.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/dom/index.ts)
- [src/jsx/dom/client.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/dom/client.ts)
- [src/jsx/dom/css.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/dom/css.ts)
- [src/jsx/dom/jsx-runtime.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/dom/jsx-runtime.ts)
- [src/jsx/intrinsic-element/common.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/intrinsic-element/common.ts)
- [src/jsx/constants.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/constants.ts)
- [src/jsx/dom/utils.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/dom/utils.ts)
- [package.json](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/package.json)
- [src/jsx/types.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/types.ts)
- [src/helper/html/index.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/helper/html/index.ts)
- [src/utils/html.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/html.ts)
</details>

## Overview

Hono's JSX implementation bridges server-side rendering, streaming, and client DOM interaction [JSX Runtime](https://www.doc0.dev/docs/552ca36e-f67e-41c3-a07a-def9bd9551b0/technical/jsx-and-ui/jsx-runtime), [Client DOM and Hooks](https://www.doc0.dev/docs/552ca36e-f67e-41c3-a07a-def9bd9551b0/technical/jsx-and-ui/client-dom-and-hooks), [JSX Streaming and Suspense](https://www.doc0.dev/docs/552ca36e-f67e-41c3-a07a-def9bd9551b0/technical/jsx-and-ui/jsx-streaming-and-suspense). It provides robust APIs for component hierarchy management, context sharing, document head control, and middleware-driven layout rendering across modern edge and browser runtimes [Execution Context](https://www.doc0.dev/docs/552ca36e-f67e-41c3-a07a-def9bd9551b0/technical/core-engine/execution-context).

Sources: [src/jsx/context.ts:8-50](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/context.ts#L8-L50), [src/middleware/jsx-renderer/index.ts:15-129](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/jsx-renderer/index.ts#L15-L129), [src/jsx/dom/intrinsic-element/components.ts:257-315](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/dom/intrinsic-element/components.ts#L257-L315)

## Context Creation and Propagation Across Runtimes

### API Mechanics and Runtime Differentiation

Hono manages context sharing through `createContext`, `Context.Provider`, and `useContext`, implemented separately for server string rendering and client-side DOM reconciliation. The `Context<T>` interface extends component types with a `values` array holding active context states and a `Provider` property pointing to the context itself. When initialized via `createContext<T>(defaultValue: T)`, it registers the context instance in the `globalContexts` array.

Sources: [src/jsx/context.ts:8-14](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/context.ts#L8-L14), [src/jsx/context.ts:41-47](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/context.ts#L41-L47), [src/jsx/dom/context.ts:45-51](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/dom/context.ts#L45-L51)

| Runtime Environment | Implementation Target | Provider Mechanism | Error / Cleanup Handling |
| :--- | :--- | :--- | :--- |
| Server (`src/jsx/context.ts`) | `FC<PropsWithChildren<{ value: T }>>` | Pushes to `values`, stringifies children, pops in `finally` / `catch`. | `try...catch` pops value on synchronous exception; `.finally()` pops on promises. |
| Client DOM (`src/jsx/dom/context.ts`) | `Function` (`createContextProviderFunction`) | Injects internal tag functions before and after child nodes to push/pop values. | `DOM_ERROR_HANDLER` pops value and rethrows error during DOM reconciliation. |

Sources: [src/jsx/context.ts:17-40](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/context.ts#L17-L40), [src/jsx/dom/context.ts:7-43](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/dom/context.ts#L7-L43)

> [!NOTE]
> In the server runtime, asynchronous children returning a `Promise` keep the context value active until settled. The `.finally()` handler ensures `values.pop()` executes whether the promise resolves or rejects, preventing stack corruption across concurrent requests.

Sources: [src/jsx/context.ts:32-35](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/context.ts#L32-L35)

### Consumption and Value Resolution

Consuming context values relies on `useContext`, which inspects the last element of the context's `values` stack via `.at(-1)`. Because nested providers push new entries onto the `values` array, `useContext` naturally retrieves the innermost provider's value.

```typescript
export const useContext = <T>(context: Context<T>): T => {
  return context.values.at(-1) as T
}
```

Sources: [src/jsx/context.ts:52-54](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/context.ts#L52-L54)

> [!WARNING]
> Modifying or mutating the `values` array directly outside of provider lifecycle execution corrupts context resolution for subsequent renders, especially in shared server runtimes where `globalContexts` retains references across requests.

Sources: [src/jsx/context.ts:13-16](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/context.ts#L13-L16)

## Error Handling with ErrorBoundary

### Error Capture and Fallback Resolution

Hono provides `ErrorBoundary` components to intercept errors during server-side rendering and client-side DOM reconciliation[JSX Runtime](https://www.doc0.dev/docs/552ca36e-f67e-41c3-a07a-def9bd9551b0/technical/jsx-and-ui/jsx-runtime), [Client DOM and Hooks](https://www.doc0.dev/docs/552ca36e-f67e-41c3-a07a-def9bd9551b0/technical/jsx-and-ui/client-dom-and-hooks). On the server, `ErrorBoundary` accepts `fallback`, `fallbackRender`, and `onError` properties, mapping child components while monitoring for exceptions during early resolution and promise settlement [src/jsx/components.ts:52-58](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/components.ts#L52-L58). When an error is thrown, the component invokes `resolveFallbackStr` to process string or asynchronous fallback content [src/jsx/components.ts:70-81](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/components.ts#L70-L81).

```typescript
const resolveFallbackStr = async () => {
  const awaitedFallback = await fallback
  if (typeof awaitedFallback === 'string') {
    fallbackStr = awaitedFallback
  } else {
    fallbackStr = await awaitedFallback?.toString()
    if (typeof fallbackStr === 'string') {
      // should not apply `raw` if fallbackStr is undefined, null, or boolean
      fallbackStr = raw(fallbackStr)
    }
  }
}
```
Sources: [src/jsx/components.ts:70-81](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/components.ts#L70-L81)

The server execution call-chain for fallback text processing proceeds through specific internal helpers:
1. `ErrorBoundary` intercepts the component error [src/jsx/components.ts:92-98](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/components.ts#L92-L98).
2. `resolveFallbackStr` awaits the fallback value and prepares its string representation [src/jsx/components.ts:70-81](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/components.ts#L70-L81).
3. `raw` wraps the resulting string with HTML-escaped flags when valid [src/jsx/components.ts:78](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/components.ts#L78).

```mermaid
sequenceDiagram
    participant ErrorBoundary as ErrorBoundary (src/jsx/components.ts)
    participant resolveFallbackStr as resolveFallbackStr (src/jsx/components.ts)
    participant raw as raw (src/utils/html.ts)

    ErrorBoundary->>resolveFallbackStr: Await and inspect fallback prop
    resolveFallbackStr->>raw: Wrap string fallback with escape metadata
```
Sources: [src/jsx/components.ts:52-81](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/components.ts#L52-L81), [src/utils/html.ts:40-46](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/html.ts#L40-L46)

> [!NOTE]
> If a fallback prop is a promise or contains asynchronous children, `ErrorBoundary` defers rendering error templates until resolution fails, injecting script targets (`data-hono-target`) to swap placeholder templates on the client.

Sources: [src/jsx/components.ts:102-128](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/components.ts#L102-L128)

### Client DOM Error Boundaries

In browser environments, the DOM implementation of `ErrorBoundary` attaches an error handler symbol (`DOM_ERROR_HANDLER`) to rendered fragment nodes [src/jsx/dom/components.ts:7-23](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/dom/components.ts#L7-L23).

```typescript
> = (({ children, fallback, fallbackRender, onError }: any) => {
  const res = Fragment({ children })
  ;(res as any)[DOM_ERROR_HANDLER] = (err: any) => {
    if (err instanceof Promise) {
      throw err
    }
    onError?.(err)
    return fallbackRender?.(err) || fallback
  }
  return res
}) as any
```
Sources: [src/jsx/dom/components.ts:13-23](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/dom/components.ts#L13-L23)

| Symbol Constant | File Origin | Target Purpose |
| :--- | :--- | :--- |
| `DOM_RENDERER` | `src/jsx/constants.ts:1` | Identifies primary node render functions. |
| `DOM_ERROR_HANDLER` | `src/jsx/constants.ts:2` | Assigns catch handlers to fragments for error recovery. |
| `DOM_STASH` | `src/jsx/constants.ts:3` | Stores hook state arrays for client components. |
| `DOM_INTERNAL_TAG` | `src/jsx/constants.ts:4` | Marks internal wrapper elements during reconciliation. |

Sources: [src/jsx/constants.ts:1-4](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/constants.ts#L1-L4)

> [!WARNING]
> Non-promise errors thrown inside client DOM `ErrorBoundary` nodes invoke `onError` and immediately return `fallbackRender` or `fallback`, whereas promise rejections are rethrown to trigger suspense fallback handling [src/jsx/dom/components.ts:15-21](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/dom/components.ts#L15-L21).

Sources: [src/jsx/dom/components.ts:15-21](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/dom/components.ts#L15-L21)

## Document Metadata and Intrinsic Component Hoisting

### Deduplication Keys and Strategy

Hono manages document metadata elements—such as `title`, `meta`, `link`, `script`, and `style`—through specialized component wrappers that support server-side hoisting and deduplication [src/jsx/intrinsic-element/common.ts:3-9](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/intrinsic-element/common.ts#L3-L9). The deduplication configuration relies on mapping intrinsic tag names to keys used for uniqueness checks during stream serialization [src/jsx/intrinsic-element/common.ts:3-9](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/intrinsic-element/common.ts#L3-L9).

```typescript
export const deDupeKeyMap: Record<string, string[]> = {
  title: [],
  script: ['src'],
  style: ['data-href'],
  link: ['href'],
  meta: ['name', 'httpEquiv', 'charset', 'itemProp'],
}
```
Sources: [src/jsx/intrinsic-element/common.ts:3-9](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/intrinsic-element/common.ts#L3-L9)

| Intrinsic Tag | Deduplication Key(s) | Sorting Behavior |
| :--- | :--- | :--- |
| `title` | `[]` (none) | Unsorted |
| `script` | `['src']` | Unsorted |
| `style` | `['data-href']` | Sorted via `data-precedence` |
| `link` | `['href']` | Sorted if stylesheet with precedence |
| `meta` | `['name', 'httpEquiv', 'charset', 'itemProp']` | Unsorted |

Sources: [src/jsx/intrinsic-element/common.ts:3-9](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/intrinsic-element/common.ts#L3-L9), [src/jsx/intrinsic-element/components.ts:101-105](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/intrinsic-element/components.ts#L101-L105)

> [!NOTE]
> If a `meta` tag includes an `itemProp` attribute, it bypasses hoisting logic entirely and renders immediately without deduplication [src/jsx/intrinsic-element/components.ts:97-99](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/intrinsic-element/components.ts#L97-L99).

Sources: [src/jsx/intrinsic-element/components.ts:97-99](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/intrinsic-element/components.ts#L97-L99)

### Server-Side Hoisting and Stream Injection

During server rendering, `documentMetadataTag` intercepts metadata nodes, generates their string representations, and attaches an `HtmlEscapedCallback` via `insertIntoHead` [src/jsx/intrinsic-element/components.ts:96-119](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/intrinsic-element/components.ts#L96-L119). When the HTML stream buffer encounters the `</head>` closing tag, accumulated metadata items are deduplicated against recorded maps and injected directly before the tag [src/jsx/intrinsic-element/components.ts:21-91](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/intrinsic-element/components.ts#L21-L91).

```typescript
let duped = false
const deDupeKeys = deDupeKeyMap[tagName]
const deDupeByKey = shouldDeDupeByKey(tagName, precedence !== undefined)
if (deDupeByKey) {
  LOOP: for (const [, tagProps] of tags) {
    if (
      tagName === 'link' &&
      !(tagProps.rel === 'stylesheet' && tagProps[dataPrecedenceAttr] !== undefined)
    ) {
      continue
    }
    for (const key of deDupeKeys) {
      if ((tagProps?.[key] ?? null) === props?.[key]) {
        duped = true
        break LOOP
      }
    }
  }
}
```
Sources: [src/jsx/intrinsic-element/components.ts:36-54](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/intrinsic-element/components.ts#L36-L54)

Stylesheets with precedence attributes utilize `dataPrecedenceAttr` (`data-precedence`) to order style and link elements within the head block based on unique precedence strings [src/jsx/intrinsic-element/common.ts:13-16](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/intrinsic-element/common.ts#L13-L16), [src/jsx/intrinsic-element/components.ts:66-81](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/intrinsic-element/components.ts#L66-L81).

> [!WARNING]
> Link elements lacking a stylesheet relationship, or containing explicit `onLoad` or `onError` handlers, skip server-side head hoisting and fall back to standard inline rendering [src/jsx/intrinsic-element/components.ts:163-168](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/intrinsic-element/components.ts#L163-L168).

Sources: [src/jsx/intrinsic-element/components.ts:163-168](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/intrinsic-element/components.ts#L163-L168)

## Component Tree Rendering with JSX Renderer Middleware

### Setup and Configuration

The `jsxRenderer` middleware intercepts Hono requests to inject layout wrappers, provide a request context via `RequestContext`, and configure response serialization [src/middleware/jsx-renderer/index.ts:116-129](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/jsx-renderer/index.ts#L116-L129). It accepts an optional `component` layout function and an `options` object or factory callback defining `docType` and `stream` behavior [src/middleware/jsx-renderer/index.ts:33-38](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/jsx-renderer/index.ts#L33-L38).

```typescript
type RendererOptions = {
  docType?: boolean | string
  stream?: boolean | Record<string, string>
}
```
Sources: [src/middleware/jsx-renderer/index.ts:18-21](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/jsx-renderer/index.ts#L18-L21)

| Option Key | Type | Default Value | Purpose |
| :--- | :--- | :--- | :--- |
| `docType` | `boolean \| string` | `true` (`<!DOCTYPE html>`) | Prepends a document type string or suppresses it when set to `false` [[src/middleware/jsx-renderer/index.ts:19` | [src/middleware/jsx-renderer/index.ts:42-47](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/jsx-renderer/index.ts#L42-L47)], |
| `stream` | `boolean \| Record<string, string>` | `false` | Enables chunked HTML streaming response or custom stream headers [[src/middleware/jsx-renderer/index.ts:20` | [src/middleware/jsx-renderer/index.ts:66-75](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/jsx-renderer/index.ts#L66-L75)] |

Sources: [src/middleware/jsx-renderer/index.ts:18-21](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/jsx-renderer/index.ts#L18-L21), [src/middleware/jsx-renderer/index.ts:42-47](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/jsx-renderer/index.ts#L42-L47), [src/middleware/jsx-renderer/index.ts:66-75](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/jsx-renderer/index.ts#L66-L75)

> [!NOTE]
> When `options.stream` is set to `true`, the middleware automatically sets standard headers including `Transfer-Encoding: chunked`, `Content-Type: text/html; charset=UTF-8`, and `Content-Encoding: Identity` [src/middleware/jsx-renderer/index.ts:67-70](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/jsx-renderer/index.ts#L67-L70).

Sources: [src/middleware/jsx-renderer/index.ts:67-70](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/jsx-renderer/index.ts#L67-L70)

### Call-Chain Execution Walkthrough

When `c.render()` is invoked during request handling, execution flows through the renderer generation phase down to template evaluation and callback resolution.

1. `jsxRenderer` — Registers the layout wrapper and assigns the renderer function generated by `createRenderer` to the context [src/middleware/jsx-renderer/index.ts:116-129](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/jsx-renderer/index.ts#L116-L129).
Sources: [src/middleware/jsx-renderer/index.ts:116-129](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/jsx-renderer/index.ts#L116-L129)
2. `createRenderer` — Resolves options, wraps the layout component with user children inside a `RequestContext.Provider`, and delegates to either `renderToReadableStream` or `c.html` [src/middleware/jsx-renderer/index.ts:33-80](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/jsx-renderer/index.ts#L33-L80).
Sources: [src/middleware/jsx-renderer/index.ts:33-80](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/jsx-renderer/index.ts#L33-L80)
3. `html` — Parses template strings and values into a buffer, handling raw injection and deferred callbacks [src/helper/html/index.ts:11-56](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/helper/html/index.ts#L11-L56).
Sources: [src/helper/html/index.ts:11-56](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/helper/html/index.ts#L11-L56)
4. `resolveCallbackSync` — Iterates through any registered `HtmlEscapedCallback` functions at the stringify phase to finalize output buffer content [src/utils/html.ts:129-140](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/html.ts#L129-L140).
Sources: [src/utils/html.ts:129-140](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/html.ts#L129-L140)

```mermaid
sequenceDiagram
    participant Middleware as jsxRenderer
    participant Renderer as createRenderer
    participant HtmlHelper as html
    participant Callback as resolveCallbackSync
    
    Middleware->>Renderer: c.setRenderer(...)
    Renderer->>HtmlHelper: html`${raw(docType)}${jsx(...)}`
    HtmlHelper->>Callback: resolveCallbackSync(...)
```
Sources: [src/middleware/jsx-renderer/index.ts:33-129](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/jsx-renderer/index.ts#L33-L129), [src/helper/html/index.ts:11-56](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/helper/html/index.ts#L11-L56), [src/utils/html.ts:129-140](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/html.ts#L129-L140)

> [!WARNING]
> Attempting to call `useRequestContext()` outside of a tree wrapped by `RequestContext` throws an error stating that `RequestContext is not provided` [src/middleware/jsx-renderer/index.ts:155-164](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/jsx-renderer/index.ts#L155-L164).

Sources: [src/middleware/jsx-renderer/index.ts:155-164](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/jsx-renderer/index.ts#L155-L164)

## Form Handling and Action Integration

### Client-Side Form Action Dispatch

Client-side form handling supports action functions by wrapping intrinsic `form` elements with a `FormContext` provider and intercepting submit events. When a submit event occurs on a trusted event, the handler extracts form data using `FormData`, updates the state with pending data and dirtiness flags, and executes the provided action function. If the action function returns a promise, it registers the action and awaits its completion before resetting the form state.

```typescript
const [state, setState] = useState<[FormData | null, boolean]>([null, false])
const onSubmit = useCallback<(ev: SubmitEvent | CustomEvent) => void>(
  async (ev: SubmitEvent | CustomEvent) => {
    const currentAction = ev.isTrusted
      ? action
      : (ev as CustomEvent).detail[customEventFormAction]
    if (typeof currentAction !== 'function') {
      return
    }

    ev.preventDefault()
    const formData = new FormData(ev.target as HTMLFormElement)
    setState([formData, true])
    const actionRes = currentAction(formData)
    if (actionRes instanceof Promise) {
      registerAction(actionRes)
      await actionRes
    }
    setState([null, true])
  },
  []
)
```
Sources: [src/jsx/dom/intrinsic-element/components.ts:332-353](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/dom/intrinsic-element/components.ts#L332-L353)

> [!NOTE]
> Form-actionable elements such as submit buttons intercept click events when a `formAction` function is supplied, preventing default navigation and dispatching a custom `submit` event carrying the action reference via `customEventFormAction`.
> Sources: [src/jsx/dom/intrinsic-element/components.ts:388-405](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/dom/intrinsic-element/components.ts#L388-L405)

### Server-Side Permalink Resolution

On the server side, intrinsic `form` components inspect the `action` property to verify if it is a function. If the action function contains a `PERMALINK` symbol attached to it, the action is transformed into its corresponding string permalink route for static or server-rendered markup generation.

```typescript
export const form: FC<
  PropsWithChildren<{
    action?: Function | string
    method?: 'get' | 'post'
  }>
> = (props) => {
  if (typeof props.action === 'function') {
    props.action = PERMALINK in props.action ? (props.action[PERMALINK] as string) : undefined
  }
```
Sources: [src/jsx/intrinsic-element/components.ts:182-190](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/intrinsic-element/components.ts#L182-L190)

> [!WARNING]
> Passing a function as a form action without an associated `PERMALINK` symbol during server-side rendering results in an undefined action attribute value.
> Sources: [src/jsx/intrinsic-element/components.ts:188-190](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/jsx/intrinsic-element/components.ts#L188-L190)

## Related

- [JSX Runtime](https://www.doc0.dev/docs/552ca36e-f67e-41c3-a07a-def9bd9551b0/technical/jsx-and-ui/jsx-runtime)
- [JSX Streaming and Suspense](https://www.doc0.dev/docs/552ca36e-f67e-41c3-a07a-def9bd9551b0/technical/jsx-and-ui/jsx-streaming-and-suspense)


## Sitemap

See the full [sitemap](https://www.doc0.dev/docs/552ca36e-f67e-41c3-a07a-def9bd9551b0/llms.txt) for all pages in this wiki.
