cloudflare-r2
Store objects with R2's S3-compatible storage on Cloudflare's edge. Use when: uploading/downloading files, configuring CORS, generating presigned URLs, multipart uploads, managing metadata, or troubleshooting R2_ERROR, CORS failures, presigned URL issues, or quota errors.
What this skill does
# Cloudflare R2 Object Storage **Status**: Production Ready ✅ **Last Updated**: 2025-10-21 **Dependencies**: cloudflare-worker-base (for Worker setup) **Latest Versions**: [email protected], @cloudflare/[email protected], [email protected] --- ## Quick Start (5 Minutes) ### 1. Create R2 Bucket ```bash # Via Wrangler CLI (recommended) npx wrangler r2 bucket create my-bucket # Or via Cloudflare Dashboard # https://dash.cloudflare.com → R2 Object Storage → Create bucket ``` **Bucket Naming Rules:** - 3-63 characters - Lowercase letters, numbers, hyphens only - Must start/end with letter or number - Globally unique within your account ### 2. Configure R2 Binding Add to your `wrangler.jsonc`: ```jsonc { "name": "my-worker", "main": "src/index.ts", "compatibility_date": "2025-10-11", "r2_buckets": [ { "binding": "MY_BUCKET", // Available as env.MY_BUCKET in your Worker "bucket_name": "my-bucket", // Name from wrangler r2 bucket create "preview_bucket_name": "my-bucket-preview" // Optional: separate bucket for dev } ] } ``` **CRITICAL:** - `binding` is how you access the bucket in code (`env.MY_BUCKET`) - `bucket_name` is the actual R2 bucket name - `preview_bucket_name` is optional but recommended for separate dev/prod data ### 3. Basic Upload/Download ```typescript // src/index.ts import { Hono } from 'hono'; type Bindings = { MY_BUCKET: R2Bucket; }; const app = new Hono<{ Bindings: Bindings }>(); // Upload file app.put('/upload/:filename', async (c) => { const filename = c.req.param('filename'); const body = await c.req.arrayBuffer(); try { const object = await c.env.MY_BUCKET.put(filename, body, { httpMetadata: { contentType: c.req.header('content-type') || 'application/octet-stream', }, }); return c.json({ success: true, key: object.key, size: object.size, etag: object.etag, }); } catch (error: any) { console.error('R2 Upload Error:', error.message); return c.json({ error: 'Upload failed' }, 500); } }); // Download file app.get('/download/:filename', async (c) => { const filename = c.req.param('filename'); try { const object = await c.env.MY_BUCKET.get(filename); if (!object) { return c.json({ error: 'File not found' }, 404); } return new Response(object.body, { headers: { 'Content-Type': object.httpMetadata?.contentType || 'application/octet-stream', 'ETag': object.httpEtag, 'Cache-Control': object.httpMetadata?.cacheControl || 'public, max-age=3600', }, }); } catch (error: any) { console.error('R2 Download Error:', error.message); return c.json({ error: 'Download failed' }, 500); } }); export default app; ``` ### 4. Deploy and Test ```bash # Deploy npx wrangler deploy # Test upload curl -X PUT https://my-worker.workers.dev/upload/test.txt \ -H "Content-Type: text/plain" \ -d "Hello, R2!" # Test download curl https://my-worker.workers.dev/download/test.txt ``` --- ## R2 Workers API ### Type Definitions ```typescript // Add to env.d.ts or worker-configuration.d.ts interface Env { MY_BUCKET: R2Bucket; // ... other bindings } // For Hono type Bindings = { MY_BUCKET: R2Bucket; }; const app = new Hono<{ Bindings: Bindings }>(); ``` ### put() - Upload Objects **Signature:** ```typescript put(key: string, value: ReadableStream | ArrayBuffer | ArrayBufferView | string | Blob, options?: R2PutOptions): Promise<R2Object | null> ``` **Basic Usage:** ```typescript // Upload from request body await env.MY_BUCKET.put('path/to/file.txt', request.body); // Upload string await env.MY_BUCKET.put('config.json', JSON.stringify({ foo: 'bar' })); // Upload ArrayBuffer await env.MY_BUCKET.put('image.png', await file.arrayBuffer()); ``` **With Metadata:** ```typescript const object = await env.MY_BUCKET.put('document.pdf', fileData, { httpMetadata: { contentType: 'application/pdf', contentLanguage: 'en-US', contentDisposition: 'attachment; filename="report.pdf"', contentEncoding: 'gzip', cacheControl: 'public, max-age=86400', }, customMetadata: { userId: '12345', uploadDate: new Date().toISOString(), version: '1.0', }, }); ``` **Conditional Uploads (Prevent Overwrites):** ```typescript // Only upload if file doesn't exist const object = await env.MY_BUCKET.put('file.txt', data, { onlyIf: { uploadedBefore: new Date('2020-01-01'), // Any date before R2 existed }, }); if (!object) { // File already exists, upload prevented return c.json({ error: 'File already exists' }, 409); } // Only upload if etag matches (update specific version) const object = await env.MY_BUCKET.put('file.txt', data, { onlyIf: { etagMatches: existingEtag, }, }); ``` **With Checksums:** ```typescript // R2 will verify the checksum const md5Hash = await crypto.subtle.digest('MD5', fileData); await env.MY_BUCKET.put('file.txt', fileData, { md5: md5Hash, }); ``` ### get() - Download Objects **Signature:** ```typescript get(key: string, options?: R2GetOptions): Promise<R2ObjectBody | null> ``` **Basic Usage:** ```typescript // Get full object const object = await env.MY_BUCKET.get('file.txt'); if (!object) { return c.json({ error: 'Not found' }, 404); } // Return as response return new Response(object.body, { headers: { 'Content-Type': object.httpMetadata?.contentType || 'application/octet-stream', 'ETag': object.httpEtag, }, }); ``` **Read as Different Formats:** ```typescript const object = await env.MY_BUCKET.get('data.json'); if (object) { const text = await object.text(); // As string const json = await object.json(); // As JSON object const buffer = await object.arrayBuffer(); // As ArrayBuffer const blob = await object.blob(); // As Blob } ``` **Range Requests (Partial Downloads):** ```typescript // Get first 1MB of file const object = await env.MY_BUCKET.get('large-file.mp4', { range: { offset: 0, length: 1024 * 1024 }, }); // Get bytes 100-200 const object = await env.MY_BUCKET.get('file.bin', { range: { offset: 100, length: 100 }, }); // Get from offset to end const object = await env.MY_BUCKET.get('file.bin', { range: { offset: 1000 }, }); ``` **Conditional Downloads:** ```typescript // Only download if etag matches const object = await env.MY_BUCKET.get('file.txt', { onlyIf: { etagMatches: cachedEtag, }, }); if (!object) { // Etag didn't match, file was modified return c.json({ error: 'File changed' }, 412); } ``` ### head() - Get Metadata Only **Signature:** ```typescript head(key: string): Promise<R2Object | null> ``` **Usage:** ```typescript // Get object metadata without downloading body const object = await env.MY_BUCKET.head('file.txt'); if (object) { console.log({ key: object.key, size: object.size, etag: object.etag, uploaded: object.uploaded, contentType: object.httpMetadata?.contentType, customMetadata: object.customMetadata, }); } ``` **Use Cases:** - Check if file exists - Get file size before downloading - Check last modified date - Validate etag for caching ### delete() - Delete Objects **Signature:** ```typescript delete(key: string | string[]): Promise<void> ``` **Single Delete:** ```typescript // Delete single object await env.MY_BUCKET.delete('file.txt'); // No error if file doesn't exist (idempotent) ``` **Bulk Delete (Up to 1000 keys):** ```typescript // Delete multiple objects at once const keysToDelete = [ 'old-file-1.txt', 'old-file-2.txt', 'temp/cache-data.json', ]; await env.MY_BUCKET.delete(keysToDelete); // Much faster than individual deletes ``` **Delete with Confirmation:** ```typescript app.delete('/files/:filename', async (c) => { const filename = c.req.param('filename'); // Check if exists first const exists = await c.env.MY_BUCKET.head(filename); if (!exists) { return c.json({ error: 'F
Related in Cloud & DevOps
appbuilder-action-scaffolder
IncludedCreate, implement, deploy, and debug Adobe Runtime actions with consistent layout, validation, and error handling. Use this skill whenever the user needs to add actions to an App Builder project, understand action structure (params, response format, web/raw actions), configure actions in the manifest, use App Builder SDKs (State, Files, Events, database), deploy and invoke actions via CLI, debug action issues, or implement patterns such as webhook receivers, custom event providers, journaling consumers, large payload redirects, action sequence pipelines, and Asset Compute workers. Also trigger when users mention serverless functions in Adobe context, action logging, IMS authentication for actions, or cron-style scheduled actions.
orchestrating-datacloud
IncludedSalesforce Data Cloud product orchestrator for connect→prepare→harmonize→segment→act workflows. Use this skill when the user needs a multi-step Data Cloud pipeline, cross-phase troubleshooting, or data space and data kit management. TRIGGER when: user needs a multi-step Data Cloud pipeline, asks to set up or troubleshoot Data Cloud across phases, manages data spaces or data kits, or wants a cross-phase sf data360 workflow. DO NOT TRIGGER when: work is isolated to a single phase (use the matching phase-specific skill), the task is STDM/session tracing/parquet telemetry (use observing-agentforce), standard CRM SOQL (use querying-soql), or Apex implementation (use generating-apex).
github-project-automation
IncludedAutomate GitHub repository setup with CI/CD workflows, issue templates, Dependabot, and CodeQL security scanning. Includes 12 production-tested workflows and prevents 18 errors: YAML syntax, action pinning, and configuration. Use when: setting up GitHub Actions CI/CD, creating issue/PR templates, enabling Dependabot or CodeQL scanning, deploying to Cloudflare Workers, implementing matrix testing, or troubleshooting YAML indentation, action version pinning, secrets syntax, runner versions, or CodeQL configuration. Keywords: github actions, github workflow, ci/cd, issue templates, pull request templates, dependabot, codeql, security scanning, yaml syntax, github automation, repository setup, workflow templates, github actions matrix, secrets management, branch protection, codeowners, github projects, continuous integration, continuous deployment, workflow syntax error, action version pinning, runner version, github context, yaml indentation error
sf-datacloud
IncludedSalesforce Data Cloud product orchestrator for connect→prepare→harmonize→segment→act workflows. TRIGGER when: user needs a multi-step Data Cloud pipeline, asks to set up or troubleshoot Data Cloud across phases, manages data spaces or data kits, or wants a cross-phase `sf data360` workflow. DO NOT TRIGGER when: work is isolated to a single phase (use the matching sf-datacloud-* skill), the task is STDM/session tracing/parquet telemetry (use sf-ai-agentforce-observability), standard CRM SOQL (use sf-soql), or Apex implementation (use sf-apex).
fabric-cli
IncludedUse this skill for Fabric.so CLI workflows with the `fabric` terminal command: diagnose/install/login, search or browse a Fabric library, save notes/links/files, create folders, ask the Fabric AI assistant, manage tasks/workspaces, generate shell completion, check subscription usage, produce JSON output, and use Fabric as persistent agent memory. Do not use for Microsoft Fabric/Azure/Power BI `fab`, Daniel Miessler's Fabric framework, Python Fabric SSH, Fabric.js, or textile/fashion fabric.
lark
IncludedLark/Feishu CLI skills: lark-cli operations for docs, markdown, sheets, base, calendar, im, mail, task, okr, drive, wiki, slides, whiteboard, apps, approval, attendance, contact, vc, minutes, event. Use when the user needs to operate Lark/Feishu resources via lark-cli, send messages, manage documents, spreadsheets, calendars, tasks, OKRs, deploy web pages, or any Feishu/Lark workspace operations.