TinyOwl
English
Download

Tutorial

Compress then Upload to Cloudflare R2 on macOS

Cloudflare R2 provides zero-egress-fee object storage that pairs perfectly with static sites, technical documentation, and blogs. Learn how to connect TinyOwl directly to Cloudflare R2 so your images are compressed to WebP locally and uploaded automatically in a single action.

TinyOwl version note: Written for TinyOwl v0.7.2 (macOS 12+ on Apple Silicon).

Why Cloudflare R2 for Image Workflows?

Hosting media assets for personal websites, documentation hubs, and developer blogs on traditional cloud storage (such as AWS S3) often comes with unpredictable egress fees. When a blog post goes viral on Hacker News or Reddit, bandwidth charges can easily dwarf storage costs.

Cloudflare R2 eliminates egress fees entirely. Combined with Cloudflare’s edge network, it offers:

  • Zero Egress Fees: Download as many terabytes as you want without surprise bandwidth bills.
  • S3 API Compatibility: Works with standard S3 SDKs and desktop upload tools.
  • Custom Domain Support: Easily map a branded subdomain like https://static.yourdomain.com or https://media.yourdomain.com.
  • Usage-based pricing: R2 has included monthly usage and no Internet egress charge for its storage classes. Check Cloudflare’s current R2 pricing before choosing a storage class or estimating costs.

When paired with TinyOwl, you achieve the optimal publishing pipeline: images are compressed and converted to lightweight WebP locally on your Mac before uploading, saving bucket storage and accelerating page loads for readers globally.

TinyOwl workflow editor showing resize, compression, and upload steps.
A TinyOwl workflow can combine optional resize, required compression, and an upload destination.

Step 1: Prepare Your Cloudflare R2 Bucket and Credentials

Before opening TinyOwl, gather your bucket name and API tokens from the Cloudflare dashboard:

1. Create an R2 Bucket

  1. Log in to the Cloudflare Dashboard.
  2. In the left navigation sidebar, select R2 StorageOverview.
  3. Click Create bucket.
  4. Enter a bucket name (e.g., my-blog-assets). Bucket names must be lowercase letters, numbers, and dashes.
  5. Choose your preferred location (or select Automatic) and click Create Bucket.

2. Generate R2 S3 API Tokens

TinyOwl communicates with R2 using its S3-compatible API. You need to create an API token with write permissions:

  1. In the R2 Overview page, click Manage R2 API Tokens in the right sidebar.
  2. Click Create API token.
  3. Enter a token name (e.g., TinyOwl-Mac-Uploader).
  4. Under Permissions, select Object Read & Write.
  5. Under Specify bucket(s), you can select All buckets or restrict it specifically to your newly created bucket.
  6. Under TTL, leave it blank for permanent access or set an expiry date.
  7. Click Create API Token.
  8. CRITICAL: Copy and save the following values immediately (Cloudflare will not show the secret key again):
    • Access Key ID: A 32-character hexadecimal string.
    • Secret Access Key: A 64-character hexadecimal string.
    • Jurisdiction-specific endpoint or your Cloudflare Account ID (a 32-character string found in your dashboard URL or under R2 overview).

To copy public image links directly into your Markdown files:

  1. Go to your bucket settings in Cloudflare R2.
  2. Under Public access, click Connect Domain.
  3. Enter your custom domain or subdomain (e.g., cdn.example.com). Cloudflare will automatically configure DNS records if your domain is managed by Cloudflare.
  4. Alternatively, enable the free r2.dev test subdomain for staging purposes.

Step 2: Configure Cloudflare R2 in TinyOwl

Now open TinyOwl to configure the upload destination:

  1. Open Settings in TinyOwl (press ⌘, or click the gear icon).
  2. In the left sidebar, click Upload Providers.
  3. Click Add Upload Provider in the top right.
  4. Select Cloudflare R2 from the preset dropdown.
  5. Fill in the exact fields:
    • Provider Name: Give it a memorable name, such as Cloudflare R2 (Blog).
    • Bucket: Your exact R2 bucket name (e.g., my-blog-assets).
    • Account ID: Paste your Cloudflare Account ID. TinyOwl automatically constructs the S3 endpoint https://<ACCOUNT_ID>.r2.cloudflarestorage.com.
    • Access Key ID: Paste your R2 Access Key ID.
    • Secret Access Key: Paste your R2 Secret Access Key.
    • Region: Keep the default auto (Cloudflare R2 handles regional routing automatically).
    • Public Base URL: Enter your public access domain, such as https://cdn.example.com (do not include a trailing slash).
    • Path Prefix (Optional): If you want all uploads placed inside a top-level directory, enter e.g. images or uploads.
  6. Click Test connection at the bottom of the card.
  7. You should see a green checkmark indicating successful authentication and bucket listing.
TinyOwl Cloudflare R2 upload provider form with account, bucket, and access key fields.
Configure your Cloudflare R2 credentials once and reuse them across multiple workflows.

Step 3: Build an Automated Workflow in TinyOwl

With the provider configured, create or modify a workflow to combine compression and upload:

  1. In Settings, navigate to Workflows.
  2. Click Add workflow (or edit an existing one).
  3. Name it Blog Post WebP + R2 Upload.
  4. Configure the steps:
    • Resize Step (Optional): Click Add resize step, then select Width 1200px or Longest edge 1600px to ensure retina screenshots aren’t unnecessarily huge.
    • Compression Step (Required): Select the built-in preset WebP - Save as or create a custom WebP preset set to Balanced Q75.
    • Upload Step (Required): Click Add upload step.
      • Select your newly created Cloudflare R2 (Blog) provider.
      • Set the Path Template to {yyyy}/{mm}/{dd} (e.g., organizes assets into 2026/09/20/filename.webp).
      • Choose the Filename Strategy: original (keeps the source name) or random / timestamped to avoid key collisions.
  5. Click Use now to set this workflow as the active default across the entire app.

Now test the complete end-to-end flow:

  1. Option A: Drag to Menu Bar: Drag an image or screenshot directly onto the TinyOwl menu bar icon.
  2. Option B: Paste from Clipboard: Copy any image to your clipboard (⌘C or screenshot with ⌃⇧⌘4), activate TinyOwl, and press ⌘V.
  3. Option C: Finder Context Menu: Right-click an image in Finder ➔ Open WithTinyOwl.

TinyOwl will execute the pipeline:

  1. Resize the image if needed.
  2. Compress and transcode to WebP locally via multi-threaded Rust.
  3. Upload the resulting .webp payload to your Cloudflare R2 bucket.
  4. Display a success banner with the size reduction percentage and a Copy Link button.

Paste into your Markdown document:

![Example Markdown image syntax after copying a public URL](https://cdn.example.com/2026/09/20/architecture-diagram.webp)

Troubleshooting Common R2 Upload Issues

Symptom / ErrorRoot CauseSolution
”Test connection failed: 403 Forbidden”Token permissions or incorrect Key/SecretEnsure your R2 API Token has Object Read & Write permissions and check for trailing spaces in your Key ID or Secret.
”Account ID invalid or bucket not found (404)“Typo in Account ID or Bucket NameConfirm your 32-character Account ID from the Cloudflare URL, and check that the bucket name matches exactly (case-sensitive).
”Upload succeeds, but Copy Link is disabled”Missing Public Base URLOpen Settings ➔ Upload Providers, expand your R2 configuration, and provide a valid Public Base URL (e.g. https://cdn.yourdomain.com).
”Public link gives 404 or XML Access Denied”Bucket public access is disabled in CloudflareIn Cloudflare Dashboard, go to your R2 bucket ➔ SettingsPublic access, and ensure your Custom Domain or R2.dev subdomain is connected and active.
”Uploaded file has no file extension”Custom filename strategy misconfigurationEnsure you have selected a valid preset with WebP output enabled and set filename strategy to original or timestamped.

By integrating TinyOwl with Cloudflare R2, you eliminate manual terminal scripts, avoid SaaS monthly storage charges, and maintain a blazing-fast image publishing flow on your Mac.