Cloudflare Pages 
Cloudflare Pages is an edge platform for full-stack web applications. It serves static files and dynamic content provided by Cloudflare Workers.
Hono fully supports Cloudflare Pages. It introduces a delightful developer experience. Vite's dev server is fast, and deploying with Wrangler is super quick.
1. Setup 
A starter for Cloudflare Pages is available. Start your project with "create-hono" command. Select cloudflare-pages 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
│   └── static // Put your static files.
│       └── style.css // You can refer to it as `/static/style.css`.
├── src
│   ├── index.tsx // The entry point for server-side.
│   └── renderer.tsx
├── tsconfig.json
└── vite.config.ts2. Hello World 
Edit src/index.tsx like the following:
import { Hono } from 'hono'
import { renderer } from './renderer'
const app = new Hono()
app.get('*', renderer)
app.get('/', (c) => {
  return c.render(<h1>Hello, Cloudflare Pages!</h1>)
})
export default app3. 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. In package.json, $npm_execpath needs to be changed to your package manager of choice.
npm run deployyarn deploypnpm run deploybun run deployDeploy via the Cloudflare dashboard with GitHub 
- Log in to the Cloudflare dashboard and select your account.
- In Account Home, select Workers & Pages > Create application > Pages > Connect to Git.
- Authorize your GitHub account, and select the repository. In Set up builds and deployments, provide the following information:
| Configuration option | Value | 
|---|---|
| Production branch | main | 
| Build command | npm run build | 
| Build directory | dist | 
Bindings 
You can use Cloudflare Bindings like Variables, KV, D1, and others. In this section, let's use Variables and KV.
Create wrangler.toml 
First, create wrangler.toml for local Bindings:
touch wrangler.tomlEdit wrangler.toml. Specify Variable with the name MY_NAME.
[vars]
MY_NAME = "Hono"Create KV 
Next, make the KV. Run the following wrangler command:
wrangler kv namespace create MY_KV --previewNote down the preview_id as the following output:
{ binding = "MY_KV", preview_id = "abcdef" }Specify preview_id with the name of Bindings, MY_KV:
[[kv_namespaces]]
binding = "MY_KV"
id = "abcdef"Edit vite.config.ts 
Edit the vite.config.ts:
import devServer from '@hono/vite-dev-server'
import adapter from '@hono/vite-dev-server/cloudflare'
import build from '@hono/vite-cloudflare-pages'
import { defineConfig } from 'vite'
export default defineConfig({
  plugins: [
    devServer({
      entry: 'src/index.tsx',
      adapter, // Cloudflare Adapter
    }),
    build(),
  ],
})Use Bindings in your application 
Use Variable and KV in your application. Set the types.
type Bindings = {
  MY_NAME: string
  MY_KV: KVNamespace
}
const app = new Hono<{ Bindings: Bindings }>()Use them:
app.get('/', async (c) => {
  await c.env.MY_KV.put('name', c.env.MY_NAME)
  const name = await c.env.MY_KV.get('name')
  return c.render(<h1>Hello! {name}</h1>)
})In production 
For Cloudflare Pages, you will use wrangler.toml for local development, but for production, you will set up Bindings in the dashboard.
Client-side 
You can write client-side scripts and import them into your application using Vite's features. If /src/client.ts is the entry point for the client, simply write it in the script tag. Additionally, import.meta.env.PROD is useful for detecting whether it's running on a dev server or in the build phase.
app.get('/', (c) => {
  return c.html(
    <html>
      <head>
        {import.meta.env.PROD ? (
          <script type='module' src='/static/client.js'></script>
        ) : (
          <script type='module' src='/src/client.ts'></script>
        )}
      </head>
      <body>
        <h1>Hello</h1>
      </body>
    </html>
  )
})In order to build the script properly, you can use the example config file vite.config.ts as shown below.
import pages from '@hono/vite-cloudflare-pages'
import devServer from '@hono/vite-dev-server'
import { defineConfig } from 'vite'
export default defineConfig(({ mode }) => {
  if (mode === 'client') {
    return {
      build: {
        rollupOptions: {
          input: './src/client.ts',
          output: {
            entryFileNames: 'static/client.js',
          },
        },
      },
    }
  } else {
    return {
      plugins: [
        pages(),
        devServer({
          entry: 'src/index.tsx',
        }),
      ],
    }
  }
})You can run the following command to build the server and client script.
vite build --mode client && vite buildCloudflare Pages Middleware 
Cloudflare Pages uses its own middleware system that is different from Hono's middleware. You can enable it by exporting onRequest in a file named _middleware.ts like this:
// functions/_middleware.ts
export async function onRequest(pagesContext) {
  console.log(`You are accessing ${pagesContext.request.url}`)
  return await pagesContext.next()
}Using handleMiddleware, you can use Hono's middleware as Cloudflare Pages middleware.
// functions/_middleware.ts
import { handleMiddleware } from 'hono/cloudflare-pages'
export const onRequest = handleMiddleware(async (c, next) => {
  console.log(`You are accessing ${c.req.url}`)
  await next()
})You can also use built-in and 3rd party middleware for Hono. For example, to add Basic Authentication, you can use Hono's Basic Authentication Middleware.
// functions/_middleware.ts
import { handleMiddleware } from 'hono/cloudflare-pages'
import { basicAuth } from 'hono/basic-auth'
export const onRequest = handleMiddleware(
  basicAuth({
    username: 'hono',
    password: 'acoolproject',
  })
)If you want to apply multiple middleware, you can write it like this:
import { handleMiddleware } from 'hono/cloudflare-pages'
// ...
export const onRequest = [
  handleMiddleware(middleware1),
  handleMiddleware(middleware2),
  handleMiddleware(middleware3),
]Accessing EventContext 
You can access EventContext object via c.env in handleMiddleware.
// functions/_middleware.ts
import { handleMiddleware } from 'hono/cloudflare-pages'
export const onRequest = [
  handleMiddleware(async (c, next) => {
    c.env.eventContext.data.user = 'Joe'
    await next()
  }),
]Then, you can access the data value in via c.env.eventContext in the handler:
// functions/api/[[route]].ts
import type { EventContext } from 'hono/cloudflare-pages'
import { handle } from 'hono/cloudflare-pages'
// ...
type Env = {
  Bindings: {
    eventContext: EventContext
  }
}
const app = new Hono<Env>().basePath('/api')
app.get('/hello', (c) => {
  return c.json({
    message: `Hello, ${c.env.eventContext.data.user}!`, // 'Joe'
  })
})
export const onRequest = handle(app)