> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/honojs/hono/llms.txt
> Use this file to discover all available pages before exploring further.

# Server-Side Rendering

> Render JSX to HTML strings on the server with Hono's efficient SSR implementation

Hono's server-side JSX rendering (`hono/jsx`) converts JSX components directly to HTML strings. This approach is optimized for server performance and integrates seamlessly with Hono's request/response model.

## Setup

Configure your `tsconfig.json` for server-side JSX:

```json tsconfig.json theme={null}
{
  "compilerOptions": {
    "jsx": "react-jsx",
    "jsxImportSource": "hono/jsx"
  }
}
```

## Using c.html() with JSX

The `c.html()` method accepts JSX and returns an HTML response:

```tsx theme={null}
import { Hono } from 'hono'

const app = new Hono()

app.get('/', (c) => {
  return c.html(
    <html>
      <head>
        <title>My App</title>
      </head>
      <body>
        <h1>Hello, Hono JSX!</h1>
      </body>
    </html>
  )
})

export default app
```

## Functional Components

Create reusable components as functions:

```tsx theme={null}
import type { FC } from 'hono/jsx'

type PageProps = {
  title: string
  description?: string
}

const Page: FC<PageProps> = ({ title, description, children }) => {
  return (
    <html>
      <head>
        <meta charSet="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>{title}</title>
        {description && <meta name="description" content={description} />}
      </head>
      <body>
        <div className="container">{children}</div>
      </body>
    </html>
  )
}

app.get('/', (c) => {
  return c.html(
    <Page title="Home" description="Welcome to my site">
      <h1>Welcome!</h1>
      <p>This is the homepage.</p>
    </Page>
  )
})
```

## Props and Type Safety

Hono JSX is fully type-safe with TypeScript:

```tsx theme={null}
type ButtonProps = {
  variant: 'primary' | 'secondary' | 'danger'
  size?: 'sm' | 'md' | 'lg'
  disabled?: boolean
  onClick?: string // Event handler as string for server-side
  children: any
}

const Button: FC<ButtonProps> = ({ 
  variant, 
  size = 'md', 
  disabled = false,
  onClick,
  children 
}) => {
  const className = `btn btn-${variant} btn-${size}`
  
  return (
    <button 
      className={className} 
      disabled={disabled}
      onclick={onClick}
    >
      {children}
    </button>
  )
}

// Usage with type checking
app.get('/button', (c) => {
  return c.html(
    <div>
      <Button variant="primary" size="lg">
        Click me
      </Button>
      {/* TypeScript error: invalid variant */}
      {/* <Button variant="invalid">Error</Button> */}
    </div>
  )
})
```

## Default Props

Components can have default props:

```tsx theme={null}
type AlertProps = {
  type: 'info' | 'warning' | 'error' | 'success'
  message: string
}

const Alert: FC<AlertProps> = ({ type, message }) => {
  const icons = {
    info: 'ℹ️',
    warning: '⚠️',
    error: '❌',
    success: '✅'
  }
  
  return (
    <div className={`alert alert-${type}`}>
      <span className="icon">{icons[type]}</span>
      <span className="message">{message}</span>
    </div>
  )
}

// Set default props
Alert.defaultProps = {
  type: 'info'
}
```

Source: [src/jsx/base.ts:17-21](https://github.com/honojs/hono/blob/main/src/jsx/base.ts#L17-L21)

## Context API

Share data across components without prop drilling:

```tsx theme={null}
import { createContext, useContext } from 'hono/jsx'
import type { FC } from 'hono/jsx'

type Theme = 'light' | 'dark'

// Create a context
const ThemeContext = createContext<Theme>('light')

const ThemedButton: FC = ({ children }) => {
  const theme = useContext(ThemeContext)
  
  return (
    <button className={`btn-${theme}`}>
      {children}
    </button>
  )
}

const ThemedCard: FC = ({ children }) => {
  const theme = useContext(ThemeContext)
  
  return (
    <div className={`card-${theme}`}>
      {children}
    </div>
  )
}

app.get('/themed', (c) => {
  return c.html(
    <ThemeContext.Provider value="dark">
      <ThemedCard>
        <h2>Dark Theme Card</h2>
        <ThemedButton>Dark Button</ThemedButton>
      </ThemedCard>
    </ThemeContext.Provider>
  )
})
```

Source: [src/jsx/context.ts:15-50](https://github.com/honojs/hono/blob/main/src/jsx/context.ts#L15-L50)

## Memo for Performance

Memoize components to avoid re-rendering:

```tsx theme={null}
import { memo } from 'hono/jsx'
import type { FC } from 'hono/jsx'

type ExpensiveProps = {
  data: number[]
  multiplier: number
}

const ExpensiveComponent: FC<ExpensiveProps> = ({ data, multiplier }) => {
  const result = data.reduce((sum, n) => sum + n * multiplier, 0)
  
  return <div>Result: {result}</div>
}

// Memoize the component
const MemoizedExpensive = memo(ExpensiveComponent)

// Custom comparison function
const MemoizedWithCustomCompare = memo(
  ExpensiveComponent,
  (prevProps, nextProps) => {
    return prevProps.multiplier === nextProps.multiplier &&
           prevProps.data.length === nextProps.data.length
  }
)
```

Source: [src/jsx/base.ts:381-402](https://github.com/honojs/hono/blob/main/src/jsx/base.ts#L381-L402)

## Cloning Elements

Clone and modify existing JSX elements:

```tsx theme={null}
import { cloneElement } from 'hono/jsx'

const AddProps: FC<{ children: any }> = ({ children }) => {
  return cloneElement(children, { 
    className: 'enhanced',
    'data-enhanced': 'true' 
  })
}

app.get('/clone', (c) => {
  return c.html(
    <AddProps>
      <div>This div will have additional props</div>
    </AddProps>
  )
})
```

Source: [src/jsx/base.ts:423-440](https://github.com/honojs/hono/blob/main/src/jsx/base.ts#L423-L440)

## Children Utilities

Manipulate children with the Children API:

```tsx theme={null}
import { Children } from 'hono/jsx'

const List: FC = ({ children }) => {
  const items = Children.toArray(children)
  
  return (
    <ul>
      {items.map((child, index) => (
        <li key={index}>
          {child}
        </li>
      ))}
    </ul>
  )
}

app.get('/list', (c) => {
  return c.html(
    <List>
      <span>Item 1</span>
      <span>Item 2</span>
      <span>Item 3</span>
    </List>
  )
})
```

## Handling Events (Server-Side)

On the server, event handlers are rendered as string attributes:

```tsx theme={null}
const InteractiveButton = () => {
  return (
    <button onclick="alert('Hello!')">
      Click me
    </button>
  )
}

const FormWithHandler = () => {
  return (
    <form 
      method="POST" 
      action="/submit"
      onsubmit="return confirm('Submit form?')"
    >
      <input type="text" name="username" />
      <button type="submit">Submit</button>
    </form>
  )
}
```

<Note>
  For interactive client-side handlers, use `hono/jsx/dom` for client-side rendering.
</Note>

## SVG Support

Render SVG elements with proper namespace handling:

```tsx theme={null}
const Icon = () => {
  return (
    <svg width="24" height="24" viewBox="0 0 24 24" fill="none">
      <path 
        d="M12 2L2 7l10 5 10-5-10-5z" 
        fill="currentColor"
        strokeWidth="2"
      />
      <path 
        d="M2 17l10 5 10-5M2 12l10 5 10-5" 
        stroke="currentColor"
        strokeWidth="2"
      />
    </svg>
  )
}
```

Source: [src/jsx/base.ts:335-345](https://github.com/honojs/hono/blob/main/src/jsx/base.ts#L335-L345)

## Async Components

Components can be async for data fetching:

```tsx theme={null}
type Post = {
  id: number
  title: string
  body: string
}

const fetchPost = async (id: number): Promise<Post> => {
  const res = await fetch(`https://api.example.com/posts/${id}`)
  return res.json()
}

const PostDetail: FC<{ id: number }> = async ({ id }) => {
  const post = await fetchPost(id)
  
  return (
    <article>
      <h1>{post.title}</h1>
      <p>{post.body}</p>
    </article>
  )
}

app.get('/post/:id', async (c) => {
  const id = Number(c.req.param('id'))
  
  return c.html(
    <div>
      <PostDetail id={id} />
    </div>
  )
})
```

<Note>
  For streaming async components, see the [Streaming](/jsx/streaming) documentation.
</Note>

## Raw HTML

Insert raw HTML strings:

```tsx theme={null}
import { raw } from 'hono/helper/html'

const RawContent = () => {
  const htmlContent = '<strong>Bold text</strong>'
  
  return (
    <div>
      {raw(htmlContent)}
    </div>
  )
}
```

## Boolean Attributes

Hono automatically handles boolean attributes:

```tsx theme={null}
const FormFields = () => {
  return (
    <form>
      <input type="text" required />  {/* renders as required="" */}
      <input type="checkbox" checked={true} />  {/* renders as checked="" */}
      <input type="text" disabled={false} />  {/* disabled not rendered */}
      <button type="submit" autofocus>Submit</button>
    </form>
  )
}
```

Source: [src/jsx/base.ts:68-95](https://github.com/honojs/hono/blob/main/src/jsx/base.ts#L68-L95)

## Error Boundaries

Handle errors gracefully:

```tsx theme={null}
import { ErrorBoundary } from 'hono/jsx'

const ProblematicComponent = () => {
  throw new Error('Something went wrong!')
  return <div>This won't render</div>
}

const Fallback = () => {
  return <div>An error occurred. Please try again later.</div>
}

app.get('/with-error', (c) => {
  return c.html(
    <ErrorBoundary fallback={<Fallback />}>
      <ProblematicComponent />
    </ErrorBoundary>
  )
})
```

Source: [src/jsx/components.ts:52-231](https://github.com/honojs/hono/blob/main/src/jsx/components.ts#L52-L231)

## Layout Composition

Build complex layouts with component composition:

```tsx theme={null}
const Header: FC = () => (
  <header>
    <nav>
      <a href="/">Home</a>
      <a href="/about">About</a>
      <a href="/contact">Contact</a>
    </nav>
  </header>
)

const Footer: FC = () => (
  <footer>
    <p>&copy; 2024 My Company</p>
  </footer>
)

const Layout: FC<{ title: string }> = ({ title, children }) => (
  <html>
    <head>
      <title>{title}</title>
      <link rel="stylesheet" href="/styles.css" />
    </head>
    <body>
      <Header />
      <main>{children}</main>
      <Footer />
    </body>
  </html>
)

app.get('/', (c) => {
  return c.html(
    <Layout title="Home">
      <h1>Welcome to my site</h1>
      <p>Content goes here</p>
    </Layout>
  )
})

app.get('/about', (c) => {
  return c.html(
    <Layout title="About">
      <h1>About Us</h1>
      <p>Learn more about our company</p>
    </Layout>
  )
})
```

## Best Practices

<AccordionGroup>
  <Accordion title="Use TypeScript for type safety">
    Define proper types for all component props to catch errors at compile time.

    ```tsx theme={null}
    type Props = {
      name: string
      age: number
    }

    const User: FC<Props> = ({ name, age }) => {
      return <div>{name} is {age} years old</div>
    }
    ```
  </Accordion>

  <Accordion title="Keep components pure">
    Components should be pure functions that return consistent output for the same input.

    ```tsx theme={null}
    // Good: Pure component
    const Greeting = ({ name }: { name: string }) => {
      return <h1>Hello, {name}!</h1>
    }

    // Avoid: Side effects in render
    const BadComponent = () => {
      console.log('Rendering...') // Side effect
      return <div>Content</div>
    }
    ```
  </Accordion>

  <Accordion title="Extract reusable components">
    Break down complex UIs into smaller, reusable components.

    ```tsx theme={null}
    // Instead of one large component
    const Page = () => (
      <div>
        <header>...</header>
        <main>...</main>
        <footer>...</footer>
      </div>
    )

    // Extract into smaller components
    const Header = () => <header>...</header>
    const Main = () => <main>...</main>
    const Footer = () => <footer>...</footer>

    const Page = () => (
      <div>
        <Header />
        <Main />
        <Footer />
      </div>
    )
    ```
  </Accordion>

  <Accordion title="Use context sparingly">
    Context is great for global data, but overusing it can make components less reusable.

    ```tsx theme={null}
    // Good: Use context for truly global data
    const ThemeContext = createContext('light')

    // Avoid: Passing down local state via context
    // Instead, use props for component-specific data
    ```
  </Accordion>
</AccordionGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="DOM Rendering" icon="browser" href="/jsx/dom-rendering">
    Learn about client-side rendering with hono/jsx/dom
  </Card>

  <Card title="Streaming" icon="bolt" href="/jsx/streaming">
    Stream HTML responses with Suspense
  </Card>

  <Card title="HTML Helper" icon="code" href="/helpers/html-css">
    Use the html helper for template rendering
  </Card>

  <Card title="Middleware" icon="plug" href="/middleware/built-in">
    Use the JSX renderer middleware
  </Card>
</CardGroup>
