Install
$ agentstack add skill-bobmatnyc-claude-mpm-skills-hono-jsx ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Hono JSX - Server-Side Rendering
Overview
Hono provides a built-in JSX renderer for server-side HTML generation. It supports async components, streaming with Suspense, and integrates seamlessly with Hono's response system.
Key Features:
- Server-side JSX rendering
- Async component support
- Streaming with Suspense
- Automatic head hoisting
- Error boundaries
- Context API
- Zero client-side hydration overhead
When to Use This Skill
Use Hono JSX when:
- Building server-rendered HTML pages
- Creating email templates
- Generating static HTML
- Streaming large HTML responses
- Building MPA (Multi-Page Applications)
Not for: Interactive SPAs (use React/Vue/Svelte instead)
Configuration
TypeScript Configuration
// tsconfig.json
{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "hono/jsx"
}
}
Alternative: Pragma Comments
/** @jsx jsx */
/** @jsxImportSource hono/jsx */
Deno Configuration
// deno.json
{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "npm:hono/jsx"
}
}
Basic Usage
Simple Rendering
import { Hono } from 'hono'
const app = new Hono()
app.get('/', (c) => {
return c.html(
Hello Hono
Hello, World!
)
})
Components
import { Hono } from 'hono'
import type { FC } from 'hono/jsx'
// Define props type
type GreetingProps = {
name: string
age?: number
}
// Functional component
const Greeting: FC = ({ name, age }) => {
return (
Hello, {name}!
{age && You are {age} years old.}
)
}
const app = new Hono()
app.get('/hello/:name', (c) => {
const name = c.req.param('name')
return c.html()
})
Layout Components
import type { FC, PropsWithChildren } from 'hono/jsx'
const Layout: FC> = ({ title, children }) => {
return (
{title}
Home
About
{children}
© 2025 My App
)
}
app.get('/', (c) => {
return c.html(
Welcome!
This is my home page.
)
})
Async Components
Basic Async
const AsyncUserList: FC = async () => {
const users = await fetchUsers()
return (
{users.map(user => (
{user.name}
))}
)
}
app.get('/users', async (c) => {
return c.html()
})
Nested Async Components
const UserProfile: FC = async ({ id }) => {
const user = await fetchUser(id)
return (
{user.name}
{user.email}
)
}
const UserPosts: FC = async ({ userId }) => {
const posts = await fetchUserPosts(userId)
return (
Posts
{posts.map(post => (
{post.title}
{post.excerpt}
))}
)
}
Streaming with Suspense
Basic Streaming
import { Suspense, renderToReadableStream } from 'hono/jsx/streaming'
const SlowComponent: FC = async () => {
await new Promise(resolve => setTimeout(resolve, 2000))
return Loaded after 2 seconds!
}
app.get('/stream', (c) => {
const stream = renderToReadableStream(
Streaming Demo
Loading...}>
)
return c.body(stream, {
headers: {
'Content-Type': 'text/html; charset=UTF-8',
'Transfer-Encoding': 'chunked'
}
})
})
Multiple Suspense Boundaries
const Page: FC = () => {
return (
Dashboard
Loading user...}>
Loading stats...}>
Loading feed...}>
)
}
Error Boundaries
import { ErrorBoundary } from 'hono/jsx'
const RiskyComponent: FC = () => {
if (Math.random() > 0.5) {
throw new Error('Random error!')
}
return Success!
}
const ErrorFallback: FC = ({ error }) => {
return (
Something went wrong
{error.message}
)
}
app.get('/risky', (c) => {
return c.html(
)
})
Async Error Boundaries
const AsyncRiskyComponent: FC = async () => {
const data = await fetchData()
if (!data) {
throw new Error('Data not found')
}
return {data}
}
// Error boundary catches async errors too
Error: {error.message}}>
Context API
Creating Context
import { createContext, useContext } from 'hono/jsx'
type Theme = 'light' | 'dark'
const ThemeContext = createContext('light')
const ThemedButton: FC = ({ label }) => {
const theme = useContext(ThemeContext)
const className = theme === 'dark' ? 'btn-dark' : 'btn-light'
return {label}
}
const App: FC = ({ theme, children }) => {
return (
{children}
)
}
app.get('/', (c) => {
const theme = c.req.query('theme') as Theme || 'light'
return c.html(
)
})
Head Hoisting
Tags like `, , , and are automatically hoisted to `:
const Page: FC = ({ title, children }) => {
return (
{/* Base head content */}
{/* These will be hoisted to head! */}
{title}
{children}
)
}
// Even from nested components
const SEO: FC = ({ title, description }) => {
return (
<>
{title}
)
}
const Article: FC = ({ article }) => {
return (
{article.title}
{article.content}
)
}
Raw HTML
dangerouslySetInnerHTML
const RawHtml: FC = ({ html }) => {
return
}
// Usage
const markdown = await renderMarkdown(content)
Raw Helper
import { raw } from 'hono/html'
const Page: FC = () => {
return (
{raw('console.log("Hello")')}
)
}
Fragments
import { Fragment } from 'hono/jsx'
// Using Fragment
const List: FC = () => {
return (
Item 1
Item 2
Item 3
)
}
// Using short syntax
const List2: FC = () => {
return (
<>
Item 1
Item 2
Item 3
)
}
Memoization
import { memo } from 'hono/jsx'
// Expensive to compute
const ExpensiveComponent: FC = ({ data }) => {
const processed = data.map(item => item.toUpperCase()).join(', ')
return {processed}
}
// Memoize the result
const MemoizedExpensive = memo(ExpensiveComponent)
// Won't recompute if data is the same
Integration Patterns
With HTMX
const TodoList: FC = ({ todos }) => {
return (
{todos.map(todo => (
{todo.text}
Delete
))}
)
}
app.get('/todos', async (c) => {
const todos = await getTodos()
return c.html(
Todos
Add
)
})
app.post('/todos', async (c) => {
const { text } = await c.req.parseBody()
const todo = await createTodo(text as string)
return c.html(
{todo.text}
Delete
)
})
With Tailwind CSS
const Button: FC = ({ variant, children }) => {
const baseClasses = 'px-4 py-2 rounded font-medium transition-colors'
const variantClasses = variant === 'primary'
? 'bg-blue-600 text-white hover:bg-blue-700'
: 'bg-gray-200 text-gray-800 hover:bg-gray-300'
return (
{children}
)
}
Quick Reference
Key Imports
import type { FC, PropsWithChildren } from 'hono/jsx'
import { Fragment, createContext, useContext, memo } from 'hono/jsx'
import { Suspense, renderToReadableStream } from 'hono/jsx/streaming'
import { ErrorBoundary } from 'hono/jsx'
import { raw } from 'hono/html'
Response Methods
// Direct render
c.html()
// Streaming
c.body(renderToReadableStream(), {
headers: { 'Content-Type': 'text/html; charset=UTF-8' }
})
Component Types
// Basic
const Comp: FC = () => Hello
// With props
const Comp: FC = ({ name }) => {name}
// With children
const Comp: FC = ({ children }) => {children}
// Async
const Comp: FC = async () => {
const data = await fetch()
return {data}
}
Related Skills
- hono-core - Framework fundamentals
- hono-middleware - Middleware patterns
- hono-cloudflare - Edge deployment
Version: Hono 4.x Last Updated: January 2025 License: MIT
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: bobmatnyc
- Source: bobmatnyc/claude-mpm-skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.