Integrations

R2

Connect Cloudflare R2 to Convex and upload from Nuxt through the useConvexR2Upload helper.

Use this guide when you want bucket-backed uploads and metadata sync through the Convex R2 component.

The canonical validation path for this setup lives in the playground dashboard.

Before you begin

Make sure:

  • the core module is installed
  • convex.r2 is enabled in nuxt.config.ts
  • your Convex project can install @convex-dev/r2

Install the dependency

Terminal
pnpm add @convex-dev/r2

Register the Convex component

convex/convex.config.ts
import r2 from '@convex-dev/r2/convex.config.js'
import { defineApp } from 'convex/server'

const app = defineApp()
app.use(r2)

export default app

Create the Convex client API

convex/r2.ts
import type { DataModel } from './_generated/dataModel'
import { R2 } from '@convex-dev/r2'
import { componentsGeneric } from 'convex/server'

const components = componentsGeneric()
export const r2 = new R2(components.r2)

export const {
  generateUploadUrl,
  syncMetadata,
  listMetadata,
  deleteObject,
} = r2.clientApi<DataModel>()

Configure the environment

Set the R2 credentials in the Convex environment you are using for this deployment.

.env
R2_BUCKET=your-bucket
R2_ENDPOINT=https://<account-id>.r2.cloudflarestorage.com
R2_ACCESS_KEY_ID=replace-me
R2_SECRET_ACCESS_KEY=replace-me

Upload from Nuxt

app/components/R2Upload.vue
<script setup lang="ts">
import { api } from '#convex/api'

const { upload, progress } = useConvexR2Upload(api.r2)
</script>

useConvexR2Upload requests a signed URL from Convex, uploads the file directly to R2, and then calls syncMetadata.

This supported path does not add a new virtual module or a new #convex/* alias.

Verify the result

The integration is working when:

  • the file uploads successfully
  • metadata is visible through the Convex client API
  • the stored object can be listed or deleted through your R2 functions

Next steps

Copyright © 2026