Build & Deploy
How you build and deploy a hono-preact app depends on the adapter it targets. This page covers development, production builds, and deployment for each shipped adapter.
Adapters
The framework targets whichever adapter you choose. Two adapters ship today:
cloudflareAdapter() from hono-preact/adapter-cloudflare and nodeAdapter()
from hono-preact/adapter-node. You select one in vite.config.ts by passing
it to the framework plugin: honoPreact({ adapter: ... }). An adapter is
required.
Dev, build, and deploy all behave per-adapter. The rest of this page covers both flows.
Cloudflare Workers
This section assumes a cloudflareAdapter() in vite.config.ts:
import { cloudflareAdapter } from 'hono-preact/adapter-cloudflare';
// ...
plugins: [honoPreact({ adapter: cloudflareAdapter() })],
Development
npm run dev
Starts the Vite dev server. The Cloudflare adapter runs your worker inside
workerd (the real Cloudflare Workers runtime) via @cloudflare/vite-plugin,
so development mirrors production: Cloudflare bindings, the SSR runtime, and
WebSocket upgrades all behave the same as a deployed Worker. Hot module
replacement works for both client components and server code.
Production build
npm run build
A single vite build. Vite's Environment API builds the browser bundle and the
Worker bundle together; there is no separate client pass. The serverOnlyPlugin
still replaces every *.server.* import with a no-op stub so server code never
enters the browser bundle.
Output is split into two directories so worker source can never be served as a static asset:
dist/
client/ # static assets, served from Cloudflare's CDN
static/client.js # client entry
static/<name>-<hash>.js # lazy route chunks
static/<name>-<hash>.css
hono_preact/ # the Worker bundle
index.js # bundled Worker
wrangler.json # generated deploy config
The Worker directory name is derived from the name field in wrangler.jsonc
(hyphens become underscores), so hono-preact produces dist/hono_preact/.
Local preview
npm run preview
Runs vite preview, which serves the production build through workerd again.
Configuring wrangler.jsonc
wrangler.jsonc is the source of truth @cloudflare/vite-plugin reads:
{
"name": "your-app-name", // also names the dist/<name>/ worker directory
"main": "node_modules/.vite/hono-preact/server-entry.tsx",
"compatibility_date": "2026-02-22",
"compatibility_flags": ["nodejs_compat"],
"assets": {
"directory": "./dist/client",
},
}
main points at the server entry the framework generates into the Vite cache
directory; the framework writes that file before the build starts. assets
points at the client build output. No run_worker_first list is needed: the
client assets and the Worker bundle land in separate directories, so the Worker
source is never exposed through the asset store. The build also writes a
.assetsignore into dist/client/ that excludes the generated config from the
asset upload.
Deploy
npm run deploy
This runs wrangler deploy against the generated config in the Worker output
directory (dist/hono_preact/wrangler.json), which references the built Worker
and the dist/client/ assets. Run npm run build first so the output exists.
Node.js
Setup
Register the Node adapter in vite.config.ts:
import { honoPreact } from 'hono-preact/vite';
import { nodeAdapter } from 'hono-preact/adapter-node';
import { defineConfig } from 'vite';
export default defineConfig({
plugins: [honoPreact({ adapter: nodeAdapter() })],
});
@hono/node-server is a peer dependency, so install it alongside the
framework: npm install @hono/node-server. @hono/node-ws is an optional peer
if you need WebSocket upgrades.
Development
npm run dev
Starts the Vite dev server. The Node adapter handles SSR through Vite's SSR module runner, so HMR works for both client and server code.
Production build and start
vite build emits a server entry at dist/server/server-entry.js and the
client bundle under dist/client/. Start production with:
node dist/server/server-entry.js
The server listens on PORT (default 3000).
Deploying
Deploy the same way you would any Node server: a container image (Docker),
a system service (systemd), or a PaaS that runs Node processes. Static assets
must be served from dist/client/; the Node adapter serves them in-process
when you run the bundled server, so a single node process handles both
assets and SSR.
See also
- Vite Config: full
honoPreact()options reference and peer-dependency setup. - Composing Hono Middleware: adding custom Hono routes and middleware alongside the framework (via
src/api.ts).