Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion docs/1.docs/99.migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ Please upgrade to the [latest LTS](https://nodejs.org/en/download) version (>= 2

- Check your local Node.js version using `node --version` and update if necessary.
- If you use a CI/CD system for deployment, ensure that your pipeline is running Node.js 20 or higher.
- If your hosting provider manages the Node.js runtime, make sure its set to version 20, 22, or later.
- If your hosting provider manages the Node.js runtime, make sure it's set to version 20, 22, or later.

## Type Imports

Expand Down Expand Up @@ -103,6 +103,22 @@ Some (legacy) presets have been removed or renamed.
| `service_worker` | Removed due to instability |
| `firebase` | Use new firebase app hosting |

## Cloudflare Bindings Access

In Nitro v2, Cloudflare environment variables and bindings were accessible via `event.context.cloudflare.env`.

In Nitro v3, the Cloudflare preset uses [srvx](https://srvx.unjs.io/) as the underlying server layer. The Cloudflare runtime context is now attached to the request's runtime object instead of the event context.

**Migration:**

```diff
-- const { cloudflare } = event.context
-- const binding = cloudflare.env.MY_BINDING
++ const { env } = event.req.runtime.cloudflare
++ const binding = env.MY_BINDING
```
::

## Changed nitro subpath imports

Nitro v2 introduced multiple subpath exports, some of which have been removed or updated:
Expand Down
11 changes: 8 additions & 3 deletions docs/2.deploy/20.providers/cloudflare.md
Original file line number Diff line number Diff line change
Expand Up @@ -290,14 +290,19 @@ For more details on Bindings and how to use them please refer to the Cloudflare

:read-more{title="KV Storage" to="/docs/storage"}

In runtime, you can access bindings from the request event, by accessing its `context.cloudflare.env` field, this is for example how you can access a D1 bindings:
In runtime, you can access bindings from the request event via `event.req.runtime.cloudflare.env`. This is for example how you can access a D1 binding:

::warning
**Nitro v3 Breaking Change:** The `event.context.cloudflare.env` pattern from Nitro v2 no longer works in production. Use `event.req.runtime.cloudflare.env` instead. The old pattern may still appear to work in local dev (via the Wrangler proxy plugin) but will be `undefined` in production deployments.
Comment on lines +294 to +296
Copy link
Member

@RihanArfan RihanArfan Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here — with the dev plugin fix, the local dev caveat no longer applies. Can simplify to:

Suggested change
::warning
**Nitro v3 Breaking Change:** The `event.context.cloudflare.env` pattern from Nitro v2 no longer works in production. Use `event.req.runtime.cloudflare.env` instead. The old pattern may still appear to work in local dev (via the Wrangler proxy plugin) but will be `undefined` in production deployments.
**Nitro v3 Breaking Change:** The `event.context.cloudflare.env` pattern from Nitro v2 has been changed to `event.req.runtime.cloudflare.env` in Nitro v3.
::

::

```ts
import { defineHandler } from "nitro/h3";

defineHandler(async (event) => {
const { cloudflare } = event.context
const stmt = await cloudflare.env.MY_D1.prepare('SELECT id FROM table')
// Nitro v3: access Cloudflare bindings via event.req.runtime.cloudflare.env
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need the v3 code comment since these docs are for v3 rather than the migration guide.

const { env } = event.req.runtime.cloudflare
const stmt = await env.MY_D1.prepare('SELECT id FROM table')
const { results } = await stmt.all()
})
```
Expand Down