Cloudflare R2
Role in the system
Section titled “Role in the system”R2 is the Information Bearing Entity (IAO) store — it carries the physical representations of information content. Three categories of IBEs are stored:
| Category | Path pattern | Scenario | Ontological character |
|---|---|---|---|
| Design assets | assets/{hash_prefix}/{filename} | Asset Ingest | IBE carrying design asset ICE |
| JSONL archives | archives/ingest/{run_id}.jsonl | Bulk Sync | IBE carrying Process Record data |
| CSV exports | exports/csv/{export_id}.csv | CSV Export | IBE carrying Document Artifact |
Access method
Section titled “Access method”The rewrite uses R2 Worker bindings instead of the current @aws-sdk/client-s3:
// Current (removed)import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';const client = new S3Client({ region: 'auto', endpoint: `https://${ACCOUNT_ID}.r2.cloudflarestorage.com`, credentials: { accessKeyId, secretAccessKey }});
// Target (binding API)await env.R2_BUCKET.put(key, body, { httpMetadata: { contentType: 'image/png' }});
const object = await env.R2_BUCKET.get(key);const url = `${env.R2_PUBLIC_URL}/${key}`;Benefits of the binding API:
- No credentials — access is automatic via Worker binding
- No SDK dependency — eliminates
@aws-sdk/client-s3(and its transitive deps) - Lower latency — avoids external HTTP hop
- Simpler error handling — native Worker error types
Content type detection
Section titled “Content type detection”Asset uploads detect content type from file extension:
| Extensions | Content type |
|---|---|
.png, .jpg, .jpeg, .gif, .webp, .svg, .ico, .bmp | image/* |
.pdf | application/pdf |
.json | application/json |
.txt, .csv | text/* |
| (default) | application/octet-stream |
Public URL
Section titled “Public URL”Assets are served via a public R2 custom domain configured in the Cloudflare dashboard. The URL pattern is:
https://assets.bluntcases.com/{key}This bearer_entity_url replaces the CLOUDFLARE_R2_PUBLIC_URL environment variable — the domain is stable and doesn’t need per-environment configuration. The URL is stored in information_content_entity.bearer_entity_url and written to the Shopify metafield.
Multipart uploads
Section titled “Multipart uploads”For large files (design assets > 5MB), R2 supports multipart upload via the binding API:
const upload = await env.R2_BUCKET.createMultipartUpload(key);// ... upload partsawait upload.complete(parts);Most design assets are under 5MB so single-part put() is the common path.