Cloudflare Workers + Vite
You can build a full-stack application on Cloudflare Workers with Vite using the @cloudflare/vite-plugin. This setup gives you a fast Vite dev server, server-side rendering with Hono's JSX renderer, and client-side scripts bundled by Vite — all running on Cloudflare Workers.
This is the recommended way to start a new full-stack project on Cloudflare.
1. Setup
A starter for Cloudflare Workers with Vite is available. Start your project with the "create-hono" command. Select the cloudflare-workers+vite template for this example.
npm create hono@latest my-appyarn create hono my-apppnpm create hono my-appbun create hono@latest my-appdeno init --npm hono my-appMove into my-app and install the dependencies.
cd my-app
npm icd my-app
yarncd my-app
pnpm icd my-app
bun iBelow is a basic directory structure.
./
├── package.json
├── public // Put your static files here.
├── src
│ ├── index.tsx // The entry point for server-side.
│ ├── renderer.tsx
│ └── style.css
├── tsconfig.json
├── vite.config.ts
└── wrangler.jsoncThe vite.config.ts combines the Cloudflare plugin with vite-ssr-components for SSR:
import { cloudflare } from '@cloudflare/vite-plugin'
import { defineConfig } from 'vite'
import ssrPlugin from 'vite-ssr-components/plugin'
export default defineConfig({
plugins: [cloudflare(), ssrPlugin()],
})2. Hello World
Edit src/index.tsx like the following:
import { Hono } from 'hono'
import { renderer } from './renderer'
const app = new Hono()
app.use(renderer)
app.get('/', (c) => {
return c.render(<h1>Hello, Cloudflare Workers!</h1>)
})
export default appThe renderer is defined in src/renderer.tsx using Hono's JSX renderer middleware together with vite-ssr-components, which wires up Vite's client and assets:
import { jsxRenderer } from 'hono/jsx-renderer'
import { Link, ViteClient } from 'vite-ssr-components/hono'
export const renderer = jsxRenderer(({ children }) => {
return (
<html>
<head>
<ViteClient />
<Link href='/src/style.css' rel='stylesheet' />
</head>
<body>{children}</body>
</html>
)
})3. Run
Run the development server locally. Then, access http://localhost:5173 in your web browser.
npm run devyarn devpnpm devbun run dev4. Deploy
If you have a Cloudflare account, you can deploy to Cloudflare. The deploy script builds with Vite and then publishes with Wrangler.
npm run deployyarn deploypnpm run deploybun run deployBindings
You can use Cloudflare Bindings like Variables, KV, D1, and others. Configure them in wrangler.jsonc. For example, to add a Variable named MY_NAME:
{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "my-app",
"compatibility_date": "2025-08-03",
"main": "./src/index.tsx",
"vars": {
"MY_NAME": "Hono",
},
}To generate the types for your Bindings, run the cf-typegen script:
npm run cf-typegenyarn cf-typegenpnpm run cf-typegenbun run cf-typegenThis generates a CloudflareBindings interface. Pass it to Hono as generics:
const app = new Hono<{ Bindings: CloudflareBindings }>()Then access the Bindings via c.env:
app.get('/', (c) => {
return c.render(<h1>Hello! {c.env.MY_NAME}</h1>)
})Client-side
vite-ssr-components lets you load client-side scripts through Vite. Add a Script component pointing to your client entry point, and Vite handles bundling for both dev and production:
import { jsxRenderer } from 'hono/jsx-renderer'
import { Script, ViteClient } from 'vite-ssr-components/hono'
export const renderer = jsxRenderer(({ children }) => {
return (
<html>
<head>
<ViteClient />
<Script src='/src/client.ts' />
</head>
<body>{children}</body>
</html>
)
})For more details, see the @cloudflare/vite-plugin documentation and vite-ssr-components.