> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/honojs/hono/llms.txt
> Use this file to discover all available pages before exploring further.

# Cloudflare Pages

> Deploy Hono applications to Cloudflare Pages Functions

Cloudflare Pages is a JAMstack platform that supports serverless functions. You can deploy full-stack Hono applications with Pages Functions.

## Quick Start

Create a new Hono project for Cloudflare Pages:

<CodeGroup>
  ```bash npm theme={null}
  npm create hono@latest my-app
  ```

  ```bash yarn theme={null}
  yarn create hono my-app
  ```

  ```bash pnpm theme={null}
  pnpm create hono my-app
  ```

  ```bash bun theme={null}
  bun create hono my-app
  ```
</CodeGroup>

Select "cloudflare-pages" as your template when prompted.

## Installation

Add Hono to your existing Cloudflare Pages project:

```bash theme={null}
npm install hono
```

## Basic Usage

Cloudflare Pages uses a `functions` directory for serverless functions. You can use Hono with the advanced mode.

### Advanced Mode Setup

Create `functions/[[route]].ts` to handle all routes:

```typescript functions/[[route]].ts theme={null}
import { Hono } from 'hono'
import { handle } from 'hono/cloudflare-pages'

const app = new Hono()

app.get('/', (c) => c.text('Hello Cloudflare Pages!'))

app.get('/api/hello', (c) => {
  return c.json({ message: 'Hello from Pages Functions!' })
})

export const onRequest = handle(app)
```

<Note>
  The `handle` adapter converts your Hono app into a Pages Functions handler.
</Note>

## Adapter Features

### Handle Function

The `handle` function wraps your Hono app for Cloudflare Pages:

```typescript functions/[[route]].ts theme={null}
import { Hono } from 'hono'
import { handle } from 'hono/cloudflare-pages'

const app = new Hono()

app.get('/api/*', (c) => {
  return c.json({ message: 'API route' })
})

export const onRequest = handle(app)
```

### Middleware Handler

Use `handleMiddleware` to create middleware for Pages Functions:

```typescript functions/_middleware.ts theme={null}
import { handleMiddleware } from 'hono/cloudflare-pages'
import { logger } from 'hono/logger'

export const onRequest = handleMiddleware(logger())
```

### Accessing EventContext

Access the Cloudflare Pages `eventContext`:

```typescript theme={null}
import { Hono } from 'hono'
import { handle } from 'hono/cloudflare-pages'
import type { EventContext } from 'hono/cloudflare-pages'

type Env = {
  Bindings: {
    eventContext: EventContext
    MY_KV: KVNamespace
  }
}

const app = new Hono<Env>()

app.get('/api/context', (c) => {
  const { eventContext } = c.env
  
  // Use waitUntil for background tasks
  eventContext.waitUntil(
    fetch('https://api.example.com/log')
  )
  
  return c.json({ message: 'Task scheduled' })
})

export const onRequest = handle(app)
```

### Static Files

Serve static files from the `public` directory:

```typescript functions/[[route]].ts theme={null}
import { Hono } from 'hono'
import { handle, serveStatic } from 'hono/cloudflare-pages'

const app = new Hono()

// Serve static files first
app.use('/static/*', serveStatic())

app.get('/api/hello', (c) => {
  return c.json({ message: 'Hello!' })
})

export const onRequest = handle(app)
```

### Connection Info

Get connection information:

```typescript theme={null}
import { Hono } from 'hono'
import { handle, getConnInfo } from 'hono/cloudflare-pages'

const app = new Hono()

app.get('/info', (c) => {
  const info = getConnInfo(c)
  return c.json({
    remote: info.remote,
  })
})

export const onRequest = handle(app)
```

## Accessing Bindings

Access KV, D1, R2, and other bindings:

```typescript functions/[[route]].ts theme={null}
import { Hono } from 'hono'
import { handle } from 'hono/cloudflare-pages'

type Bindings = {
  MY_KV: KVNamespace
  DB: D1Database
}

const app = new Hono<{ Bindings: Bindings }>()

app.get('/kv/:key', async (c) => {
  const key = c.req.param('key')
  const value = await c.env.MY_KV.get(key)
  return c.text(value || 'Not found')
})

app.get('/db/users', async (c) => {
  const { results } = await c.env.DB.prepare(
    'SELECT * FROM users'
  ).all()
  return c.json(results)
})

export const onRequest = handle(app)
```

## Configuration

Configure bindings in `wrangler.toml`:

```toml wrangler.toml theme={null}
name = "my-hono-pages"
pages_build_output_dir = "./public"

[[kv_namespaces]]
binding = "MY_KV"
id = "your-kv-id"

[[d1_databases]]
binding = "DB"
database_name = "my-database"
database_id = "your-database-id"
```

## Deployment

<Steps>
  <Step title="Build your project">
    Build your frontend and backend:

    ```bash theme={null}
    npm run build
    ```
  </Step>

  <Step title="Deploy with Wrangler">
    Deploy using Wrangler:

    ```bash theme={null}
    wrangler pages deploy public
    ```
  </Step>

  <Step title="Deploy via Git">
    Alternatively, connect your Git repository in the Cloudflare dashboard:

    1. Go to Cloudflare Pages
    2. Click "Create a project"
    3. Connect your repository
    4. Configure build settings
    5. Deploy
  </Step>
</Steps>

## Project Structure

Typical Cloudflare Pages + Hono project structure:

```
my-app/
├── functions/
│   ├── [[route]].ts       # Main API handler
│   └── _middleware.ts     # Global middleware
├── public/
│   ├── index.html
│   └── static/
├── wrangler.toml
└── package.json
```

## Development

Run locally with Wrangler:

```bash theme={null}
wrangler pages dev public
```

This starts a local server at `http://localhost:8788` with hot reload.

## Combining with Frontend Frameworks

Cloudflare Pages works great with frontend frameworks:

### With React/Vite

```json package.json theme={null}
{
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "wrangler pages dev dist"
  }
}
```

### With Next.js

Use the `@cloudflare/next-on-pages` adapter for Next.js on Cloudflare Pages.

## Best Practices

<AccordionGroup>
  <Accordion title="Separate API and static routes">
    Use path prefixes like `/api/*` for backend routes to avoid conflicts with static files.
  </Accordion>

  <Accordion title="Use Advanced Mode">
    Advanced Mode (`functions/[[route]].ts`) gives you full control over routing.
  </Accordion>

  <Accordion title="Leverage bindings">
    Use KV, D1, and R2 for data storage instead of external databases.
  </Accordion>

  <Accordion title="Optimize bundle size">
    Keep your functions directory small for faster cold starts.
  </Accordion>
</AccordionGroup>

## Resources

<CardGroup cols={2}>
  <Card title="Cloudflare Pages Docs" icon="book" href="https://developers.cloudflare.com/pages/">
    Official Cloudflare Pages documentation
  </Card>

  <Card title="Pages Functions" icon="functions" href="https://developers.cloudflare.com/pages/platform/functions/">
    Learn about Pages Functions
  </Card>
</CardGroup>
