Skip to content

feat(hono): add the Hono JSX adapter for Pages - #731

Draft
yusukebe wants to merge 2 commits into
mainfrom
feat/hono-adapter
Draft

yusukebe wants to merge 2 commits into
mainfrom
feat/hono-adapter

Conversation

@yusukebe

@yusukebe yusukebe commented Nov 6, 2026

Copy link
Copy Markdown

Adds @void/hono, a Pages adapter for Hono JSX, next to the React, Vue, Svelte and Solid adapters. Pages, layouts, and islands are written in TSX and rendered with hono/jsx on the server and hono/jsx/dom in the browser.

// vite.config.ts
import { voidHono } from '@void/hono/plugin';
import { voidPlugin } from 'void';

export default { plugins: [voidPlugin(), voidHono()] };

Of course, you can use React, and Hono JSX doesn't have all of React's features. But Hono JSX is small, and with Hono JSX, the app doesn't need a UI library dependency. I think Hono JSX is a good option for users. If they want to write an SSR-based website, they can use Hono JSX.

Where Hono JSX fits

Hono JSX suits apps that are mostly server-rendered: content sites, Markdown, island pages with a few interactive components, and apps whose server is already written with Hono. On the server this adapter is on par with the React adapter: SSR, loaders, actions, layouts and typed routes work the same way, and the public API has the same names.

It is not a replacement for the React adapter. The differences are in the browser:

  • Hydration: Hono JSX renders the page again instead of adopting the server DOM, so focus and values typed before hydration are lost.
  • Dev updates: there is no Fast Refresh. Editing an island resets its state, and other edits reload the page.
  • Deferred props: there is no streaming SSR with Suspense and use(). Deferred is { loading, value, error }, as in the Vue, Svelte and Solid adapters.
  • Transitions: router.visit() has no resolveOn: 'data', so it does not integrate with startTransition or useActionState.
  • Ecosystem: React component libraries do not work with Hono JSX.

Apps with a lot of client-side state are better served by the React adapter. In return the client runtime is small: the whole client build of playground/hono-pages is 29 kB gzipped, against 31 kB for the Solid playground with the same pages.

What is included

  • packages/hono: the adapter. It has the same public API as the other adapters: Form, Link, useForm, useIslandForm, useRouter, useNavigation, useParams, useShared, action, Deferred and InferProps. voidHono() takes the same viewTransitions and prefetch options.
  • @void/md: Markdown pages render through Hono JSX when the Hono adapter is installed, including islands and useFrontmatter().
  • void init / create-void: Hono is a starter choice.
  • playground/hono-pages: the Solid playground ported to Hono JSX. It runs the shared browser contract.
  • Docs: a Hono tab next to each Solid tab in the Pages guides, and an @void/hono section in the API reference.
  • CI scripts: Hono is added to the packed-init and packed-consumer framework lists.

Behavior worth knowing

  • Hydration: hydrateRoot in hono/jsx/dom renders the page again instead of adopting the server DOM. The resulting DOM matches the server HTML on the playground pages, but focus and values typed before hydration are lost. The adapter calls hydrateRoot, so it picks up real hydration when Hono supports it.
  • Dev updates: Hono JSX has no Fast Refresh. An edit to an island component replaces that island without a full reload, and its state resets. Other edits reload the page.
  • Island pages in dev: island pages load the Vite client in dev even when they have no islands, so an edit reloads the page. The other adapters send no script for such pages, and the page needs a manual reload. Production output is the same as the other adapters: no JavaScript without islands. I can align this with the other adapters if you prefer.
  • Render errors: when a page throws while rendering after a client navigation, router.visit() rejects with that error and the current page stays on screen.

Not included

  • The auth client (void/client/hono, useSession).
  • void gen ssr --hono.

Testing

  • Unit tests for the plugin, the server renderer, Link, the page client and the Markdown output.
  • Integration tests: the shared Pages browser contract against `playground/honooduction build, island CSS builds, and Markdown frontmatter with islands.
  • vp run build:all, vp run build:docs, vp run check, vp lint and vp fmt --check pass.
  • vp test run: all Hono tests pass. On my machine init.test.ts, init-install.test.ts and nitro.test.ts fail, and they fail the same way without this change.
  • Packed consumer acceptance with VOID_PACKED_FRAMEWORK=hono and pnpm passes. I did not run it with npm.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Nov 6, 2026 •

Copy link
Copy Markdown

🚀 Deploying Preview to Cloudflare 🚀

Preview URL: https://feat-hono-adapter-void-cloud.voidzero-docs.workers.dev (commit 4dda94d)

This URL reflects your latest Preview deployment

Preview Deployments by commit

Status Deployment URL Commit Updated (UTC) See this deployment's details
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://1b7c8239-void-cloud.voidzero-docs.workers.dev 4dda94d 2026-11-06T08:47:39.619Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://da0f7c91-void-cloud.voidzero-docs.workers.dev ae94680 2026-11-06T08:24:45.492Z Visit the dashboard ↗

@cpojer

cpojer commented Nov 13, 2026 •

Copy link
Copy Markdown
Member

Thanks for building this prototype, it's a really valuable look into what it takes to build a UI framework adapter for Void.

The first thing I'm taking away from this work is that we should make all APIs extensible, including create-void's ability to select out-of-repo UI frameworks. Right now Void hardcodes the four supported UI frameworks and adding a new one requires extending all those lists. Ideally we do not hardcode them and expose APIs that allow extensions such as what you did in @void/md from the outside without having to change Void's core.

For deciding which UI frameworks we support in Void officially, I consider two primary factors:

  • Does it provide a great user experience
  • Does it support the same feature set as the other UI frameworks

These two are related. For example, supporting all of Void's features likely leads to a better user experience. Here are the concrete issues I see in the current implementation:

  • Hydration support in Hono is not comparable to how it works in other frameworks – I do not think we can support a framework officially in Void without complete hydration support. An alternative would be to only support server-side rendering with Hono, but again, then we are not supporting the full feature-set and it is also very close to the basic jsx streaming we already have in Void Core.
  • It's not clear to me what the actual async component and data fetching support is for this implementation. I believe they work on the server, but crash in interactive pages.
  • We have shipped a large number of changes and features since this PR was created that led to a drift across frameworks which we'd need to fix up.

There are some smaller changes as well, for example I suggest calling it "Hono JSX" to avoid people from potentially being confused about how this relates to Hono's server features.

Based on the above, we have to decide if we'll complete the feature set and bring it into Void directly, or make it possible to easily ship it as part of Hono, like @hono/void – The latter could be mentioned in Void's documentation, we could run CI on it, and I believe it would be useful for other UI frameworks who want to integrate with Void where we won't take on the maintenance effort. I can also see how we might move the Svelte and Solid adapters out of Void in the future due to low usage, but a decision has not been made yet.

Please let me know what you think.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants