Skip to main content

Cloudflare Workers + Vite

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.

npmyarnpnpmbundeno

npm create hono@latest my-app

Move into my-app and install the dependencies.

npmyarnpnpmbun

cd my-app
npm i

Below 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.jsonc

The 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 app

The 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.

npmyarnpnpmbun

npm run dev

4. Deploy

If you have a Cloudflare account, you can deploy to Cloudflare. The deploy script builds with Vite and then publishes with Wrangler.

npmyarnpnpmbun

npm run deploy

Bindings

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:

npmyarnpnpmbun

npm run cf-typegen

This 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.