Nuxt Module

Cloudflare R2

Enable the Nuxt-side R2 upload helper and connect it to the Convex R2 component.

Use this guide when you want bucket-backed uploads through Cloudflare R2 instead of Convex storage objects.

Before you begin

Make sure:

  • the core module is already installed
  • you have already generated #convex/api
  • your Convex project is ready to install the @convex-dev/r2 component

Enable the Nuxt helper

Turn on the R2 feature in nuxt.config.ts.

nuxt.config.ts
export default defineNuxtConfig({
  modules: ['nuxt-convex'],
  convex: {
    r2: true,
  },
})

This adds the useConvexR2Upload auto-import. It does not create an R2-specific alias.

Install the Convex R2 component

Terminal
pnpm add @convex-dev/r2
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 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>()

Upload from Nuxt

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

const { upload, progress, isUploading, error } = useConvexR2Upload(api.r2)

async function onSelect(event: Event) {
  const file = (event.target as HTMLInputElement).files?.[0]
  if (file)
    await upload(file)
}
</script>

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

Verify the result

The integration is working when:

  • useConvexR2Upload is available without a manual import
  • the file uploads successfully
  • the Convex-side metadata sync completes after the upload

Next steps

Copyright © 2026