Documentación

Almacenamiento (Cloudflare R2)

Almacenamiento de archivos en Cloudflare R2 — configuración del bucket, credenciales, uploads firmados y API compatible con S3.

Abrir enChatGPT (se abre en una pestaña nueva)Claude (se abre en una pestaña nueva)Cursor (se abre en una pestaña nueva)Almacenamiento de archivos en Cloudflare R2 — configuración del bucket, credenciales, uploads firmados y API compatible con S3.

Motoko Base usa Cloudflare R2 para almacenamiento de archivos. R2 es compatible con S3 — la app usa el AWS SDK con un endpoint personalizado.

Official docs: Cloudflare R2 documentation

Setup

  1. Crea un bucket R2 en el Cloudflare dashboard → R2
  2. Crea un R2 API token (Object Read & Write)
  3. Define las env vars:
VariablePurpose
R2_ACCOUNT_IDCloudflare account ID
R2_ACCESS_KEY_IDAPI token access key
R2_SECRET_ACCESS_KEYAPI token secret
R2_BUCKET_NAMEBucket name (optional /prefix suffix)
R2_PREFIXOptional key prefix override
R2_ENDPOINTOptional custom endpoint

Sin las env vars de R2 la app arranca — el demo de Storage muestra un mensaje de configuración.

How uploads work

Client → Server Action (presigned PUT URL)
   ↓
Browser uploads directly to R2
   ↓
Server validates (HEAD) → marks file ready in Postgres

Los archivos nunca se proxifican a través de Next.js. El servidor emite una URL firmada; el navegador sube a R2. Los metadatos (nombre, tamaño, propietario) viven en la tabla files.

Límites de upload y MIME types permitidos: src/features/storage/config.ts.

S3-compatible API

Cliente R2: src/lib/r2.ts — usa @aws-sdk/client-s3 con:

  • Endpoint: https://{R2_ACCOUNT_ID}.r2.cloudflarestorage.com
  • Region: auto
  • Path-style URLs (forcePathStyle: true)

Las URLs firmadas PUT (upload) y GET (download) caducan tras 10–15 minutos.

Production

  • Usa un bucket privado — acceso solo vía URLs firmadas
  • Define las credenciales como env vars solo de servidor (nunca NEXT_PUBLIC_*)
  • Los avatares (Settings) también usan R2 cuando está configurado — mismas credenciales
  • Considera reglas de lifecycle en Cloudflare para objetos antiguos — no incluidas en el starter

Para CORS: si fallan los uploads del navegador, añade el origen de tu app a la política CORS del bucket en Cloudflare. Consulta R2 CORS docs.

Where to change this

WhatWhere
R2 client & presigned URLssrc/lib/r2.ts
Upload actions & validationsrc/features/storage/actions.ts
File metadata queriessrc/features/storage/queries.ts
Limits & MIME allowlistsrc/features/storage/config.ts
Storage UIsrc/features/storage/components/dashboard/storage-page.tsx

Importa @/lib/r2 solo desde código de servidor — nunca desde client components.


Environment Variables — todas las env vars de R2.