{"id":279492,"date":"2026-03-05T04:45:19","date_gmt":"2026-03-05T04:45:19","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/cf-r2-offload-cdn\/"},"modified":"2026-03-20T05:45:38","modified_gmt":"2026-03-20T05:45:38","slug":"tp-media-offload-edge-cdn","status":"publish","type":"plugin","link":"https:\/\/fr-ca.wordpress.org\/plugins\/tp-media-offload-edge-cdn\/","author":23445124,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_crdt_document":"","version":"1.0.2","stable_tag":"1.0.2","tested":"6.9.4","requires":"6.0","requires_php":"8.0","requires_plugins":null,"header_name":"TP Media Offload & Edge CDN","header_author":"TP","header_description":"Offload WordPress media to Cloudflare R2 storage and serve via CDN with automatic image optimization (WebP\/AVIF, responsive sizes, quality control).","assets_banners_color":"c85e12","last_updated":"2026-03-20 05:45:38","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/wordpress.org\/plugins\/tp-media-offload-edge-cdn\/","header_author_uri":"https:\/\/profiles.wordpress.org\/thachpn165\/","rating":0,"author_block_rating":0,"active_installs":0,"downloads":336,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.0.0":{"tag":"1.0.0","author":"thachpn165","date":"2026-03-05 04:45:21"},"1.0.1":{"tag":"1.0.1","author":"thachpn165","date":"2026-03-20 05:20:12"},"1.0.2":{"tag":"1.0.2","author":"thachpn165","date":"2026-03-20 05:45:38"}},"upgrade_notice":{"1.0.2":"<p>Recommended update. This release republishes the 1.0.1 fixes with corrected release metadata and stronger SVN packaging verification.<\/p>","1.0.1":"<p>Recommended update. This release fixes settings schema mismatches, improves validation and queue reliability, and updates release tooling\/docs.<\/p>","1.0.0":"<p>Initial release. Please backup your database before installing.<\/p>"},"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3475104,"resolution":"128x128","location":"assets","locale":""},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3475104,"resolution":"256x256","location":"assets","locale":""},"icon.svg":{"filename":"icon.svg","revision":3475104,"resolution":false,"location":"assets","locale":false}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3475104,"resolution":"1544x500","location":"assets","locale":""}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.0.0","1.0.1","1.0.2"],"block_files":[],"assets_screenshots":[],"screenshots":{"1":"Dashboard with setup guides and statistics","2":"Storage settings with R2 credentials","3":"CDN settings with Worker deployment","4":"Bulk Actions with terminal-style activity log","5":"Media Library with offload status column","6":"System Info with debug information"},"jetpack_post_was_ever_published":false},"plugin_section":[],"plugin_tags":[3863,3882,29161,84,46891],"plugin_category":[50,59],"plugin_contributors":[257139],"plugin_business_model":[],"class_list":["post-279492","plugin","type-plugin","status-publish","hentry","plugin_tags-cdn","plugin_tags-cloudflare","plugin_tags-image-optimization","plugin_tags-media","plugin_tags-offload","plugin_category-media","plugin_category-utilities-and-tools","plugin_contributors-thachpn165","plugin_committers-thachpn165"],"banners":[],"icons":{"svg":"https:\/\/ps.w.org\/tp-media-offload-edge-cdn\/assets\/icon.svg?rev=3475104","icon":"https:\/\/ps.w.org\/tp-media-offload-edge-cdn\/assets\/icon.svg?rev=3475104","icon_2x":false,"generated":false},"screenshots":[],"raw_content":"<!--section=description-->\n<p><strong>TP Media Offload &amp; Edge CDN<\/strong> is a powerful WordPress plugin that offloads your media files to Cloudflare R2 object storage and serves them through Cloudflare's global CDN network with automatic image optimization.<\/p>\n\n<h4>Key Features<\/h4>\n\n<ul>\n<li><strong>R2 Storage Integration<\/strong> - Seamlessly upload media to Cloudflare R2 with S3-compatible API<\/li>\n<li><strong>Automatic Offload<\/strong> - New uploads are automatically offloaded to R2<\/li>\n<li><strong>Bulk Offload<\/strong> - Offload existing media library with configurable batch size<\/li>\n<li><strong>CDN Delivery<\/strong> - Serve media through Cloudflare's global CDN network<\/li>\n<li><strong>Image Optimization<\/strong> - Automatic WebP\/AVIF conversion via Cloudflare Image Transformations<\/li>\n<li><strong>Responsive Images<\/strong> - Smart srcset generation with preset breakpoints (320, 640, 768, 1024, 1280, 1536)<\/li>\n<li><strong>Quality Control<\/strong> - Configurable image quality (1-100)<\/li>\n<li><strong>Worker Auto-Deploy<\/strong> - One-click Cloudflare Worker deployment for image processing<\/li>\n<li><strong>WooCommerce Support<\/strong> - Full integration with product images and galleries<\/li>\n<li><strong>Background Processing<\/strong> - Queue-based processing with WP Cron (Action Scheduler supported)<\/li>\n<li><strong>Media Library Integration<\/strong> - Status column, bulk actions, and row actions<\/li>\n<li><strong>WP-CLI Support<\/strong> - Command line interface for bulk operations and automation<\/li>\n<\/ul>\n\n<h4>Requirements<\/h4>\n\n<ul>\n<li>WordPress 6.0 or higher<\/li>\n<li>PHP 8.0 or higher<\/li>\n<li>Cloudflare account with R2 storage enabled<\/li>\n<li>R2 bucket with public access or custom domain<\/li>\n<li>Cloudflare API Token (for Worker deployment)<\/li>\n<\/ul>\n\n<h4>How It Works<\/h4>\n\n<ol>\n<li>Configure your R2 credentials (Account ID, Access Key, Secret Key, Bucket)<\/li>\n<li>Set up your CDN URL (R2 public domain or custom domain)<\/li>\n<li>Enable auto-offload or use bulk offload for existing media<\/li>\n<li>Plugin automatically rewrites URLs to serve from CDN<\/li>\n<li>Cloudflare Worker handles image transformations on-the-fly<\/li>\n<\/ol>\n\n<h4>Security<\/h4>\n\n<ul>\n<li>API credentials encrypted with AES-256-CBC + HMAC<\/li>\n<li>Rate limiting on settings saves<\/li>\n<li>Nonce verification on all AJAX requests<\/li>\n<li>Capability checks for all admin operations<\/li>\n<li>Secure uninstall (wipes all sensitive data)<\/li>\n<\/ul>\n\n<h4>Performance<\/h4>\n\n<ul>\n<li>Batch processing to prevent memory exhaustion<\/li>\n<li>Transient caching for dashboard stats<\/li>\n<li>Conditional asset loading<\/li>\n<li>Background queue processing<\/li>\n<\/ul>\n\n<h4>Build and Generated Assets<\/h4>\n\n<p>This plugin includes compiled frontend assets in:<\/p>\n\n<ul>\n<li><code>assets\/js\/admin.js<\/code> and <code>assets\/js\/public.js<\/code><\/li>\n<li><code>assets\/css\/admin.css<\/code> and <code>assets\/css\/public.css<\/code><\/li>\n<\/ul>\n\n<p>Source files are included in the same plugin package:<\/p>\n\n<ul>\n<li>JavaScript source: <code>assets\/src\/js\/admin.js<\/code>, <code>assets\/src\/js\/public.js<\/code><\/li>\n<li>SCSS source: <code>assets\/src\/scss\/admin.scss<\/code>, <code>assets\/src\/scss\/public.scss<\/code><\/li>\n<\/ul>\n\n<p>Build steps used to generate compiled files:<\/p>\n\n<ol>\n<li><code>npm install<\/code><\/li>\n<li><code>npm run build<\/code><\/li>\n<\/ol>\n\n<p>Development watch mode:<\/p>\n\n<ul>\n<li><code>npm run dev<\/code><\/li>\n<\/ul>\n\n<h3>External services<\/h3>\n\n<p>This plugin connects to Cloudflare services to offload media and deliver files via CDN.<\/p>\n\n<h4>Cloudflare R2 Object Storage<\/h4>\n\n<ul>\n<li><strong>What it is used for:<\/strong> Store and serve media objects.<\/li>\n<li><strong>Data sent:<\/strong> Account ID, Access Key ID, Secret Access Key, bucket name, file paths, and media file contents.<\/li>\n<li><strong>When data is sent:<\/strong> During connection testing, single\/bulk offload, restore, and local-file cleanup actions.<\/li>\n<li><strong>Service provider:<\/strong> Cloudflare, Inc.<\/li>\n<li><strong>Terms of Service:<\/strong> https:\/\/www.cloudflare.com\/website-terms\/<\/li>\n<li><strong>Privacy Policy:<\/strong> https:\/\/www.cloudflare.com\/privacypolicy\/<\/li>\n<\/ul>\n\n<h4>Cloudflare API (Workers and DNS)<\/h4>\n\n<ul>\n<li><strong>What it is used for:<\/strong> Deploy\/remove Workers, validate DNS records, and enable DNS proxy for CDN routing.<\/li>\n<li><strong>Data sent:<\/strong> API token, account ID, zone ID, DNS record ID, worker configuration, and configured CDN domain.<\/li>\n<li><strong>When data is sent:<\/strong> When you click Deploy Worker, Remove Worker, Validate DNS, or Enable Proxy.<\/li>\n<li><strong>Service provider:<\/strong> Cloudflare, Inc.<\/li>\n<li><strong>Terms of Service:<\/strong> https:\/\/www.cloudflare.com\/website-terms\/<\/li>\n<li><strong>Privacy Policy:<\/strong> https:\/\/www.cloudflare.com\/privacypolicy\/<\/li>\n<\/ul>\n\n<h3>Privacy Policy<\/h3>\n\n<p>This plugin:\n* Stores your Cloudflare API credentials encrypted in your WordPress database\n* Uploads your media files to your Cloudflare R2 bucket\n* Sends required API data directly to Cloudflare services to provide plugin functionality\n* Does not include any tracking or analytics<\/p>\n\n<p>Your data stays between your WordPress site and your Cloudflare account.<\/p>\n\n<h3>Support<\/h3>\n\n<p>For support, feature requests, or bug reports:\n* Visit <a href=\"https:\/\/wordpress.org\/support\/plugin\/tp-media-offload-edge-cdn\/\">WordPress support forum<\/a>\n* Create an issue on GitHub (coming soon)<\/p>\n\n<h3>Credits<\/h3>\n\n<ul>\n<li>Built with AWS SDK for PHP for R2 compatibility<\/li>\n<li>Uses WP Cron for background processing (Action Scheduler compatible)<\/li>\n<li>Cloudflare Workers for image transformations<\/li>\n<\/ul>\n\n<h3>Disclaimer<\/h3>\n\n<p>This plugin is an independent, third-party project and is <strong>not affiliated with, endorsed by, or officially associated with Cloudflare, Inc.<\/strong> in any way. \"Cloudflare\" and \"R2\" are trademarks of Cloudflare, Inc. The use of these names is solely for descriptive purposes to indicate compatibility with Cloudflare services.<\/p>\n\n<p>This plugin is developed and maintained independently by the plugin author and the open-source community.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Upload the plugin files to <code>\/wp-content\/plugins\/tp-media-offload-edge-cdn<\/code> or install through WordPress plugins screen<\/li>\n<li>Activate the plugin through the 'Plugins' screen in WordPress<\/li>\n<li>Go to <strong>TP Media Offload &amp; Edge CDN<\/strong> in the admin menu<\/li>\n<\/ol>\n\n<h4>Initial Setup<\/h4>\n\n<p><strong>Step 1: Configure R2 Storage<\/strong><\/p>\n\n<ol>\n<li>Log in to your Cloudflare dashboard<\/li>\n<li>Go to R2 &gt; Overview and create a bucket<\/li>\n<li>Go to R2 &gt; Manage R2 API Tokens<\/li>\n<li>Create a new API token with read\/write access<\/li>\n<li>Copy Account ID, Access Key ID, and Secret Access Key<\/li>\n<li>Enter these in the plugin's Storage tab<\/li>\n<\/ol>\n\n<p><strong>Step 2: Configure CDN (Optional but Recommended)<\/strong><\/p>\n\n<ol>\n<li>In Cloudflare, set up a custom domain for your R2 bucket<\/li>\n<li>Or use the R2.dev public URL<\/li>\n<li>Enter the CDN URL in the plugin's CDN tab<\/li>\n<\/ol>\n\n<p><strong>Step 3: Deploy Worker (For Image Optimization)<\/strong><\/p>\n\n<ol>\n<li>Create a Cloudflare API Token with Workers permissions<\/li>\n<li>Enter the token in the CDN tab<\/li>\n<li>Click \"Deploy Worker\" button<\/li>\n<li>Worker will be automatically deployed<\/li>\n<\/ol>\n\n<p><strong>Step 4: Start Offloading<\/strong><\/p>\n\n<ol>\n<li>Enable \"Auto Offload\" for new uploads<\/li>\n<li>Use \"Bulk Actions\" tab to offload existing media<\/li>\n<li>Monitor progress in the terminal-style activity log<\/li>\n<\/ol>\n\n<h4>WP-CLI Commands<\/h4>\n\n<p>The plugin provides WP-CLI commands for automation and bulk operations:<\/p>\n\n<pre><code>wp cfr2 status\n<\/code><\/pre>\n\n<p>Show offload statistics (total, offloaded, not offloaded, disk saveable, pending).<\/p>\n\n<pre><code>wp cfr2 offload &lt;id|all&gt; [--dry-run] [--batch-size=50]\n<\/code><\/pre>\n\n<p>Offload media to R2. Use specific ID or \"all\" for bulk offload.<\/p>\n\n<pre><code>wp cfr2 restore &lt;id|all&gt; [--dry-run] [--batch-size=50]\n<\/code><\/pre>\n\n<p>Restore media from R2 (removes R2 metadata, reverts to local URLs).<\/p>\n\n<pre><code>wp cfr2 free-space &lt;id|all&gt; [--dry-run] [--batch-size=50]\n<\/code><\/pre>\n\n<p>Delete local files for offloaded media to free disk space.<\/p>\n\n<p><strong>Examples:<\/strong><\/p>\n\n<pre><code># Check current offload status\nwp cfr2 status\n\n# Offload single attachment\nwp cfr2 offload 123\n\n# Offload all media with larger batch size\nwp cfr2 offload all --batch-size=100\n\n# Preview what would be offloaded (dry run)\nwp cfr2 offload all --dry-run\n\n# Free disk space by removing local copies\nwp cfr2 free-space all\n<\/code><\/pre>\n\n<!--section=faq-->\n<dl>\n<dt id=\"what%20is%20cloudflare%20r2%3F\"><h3>What is Cloudflare R2?<\/h3><\/dt>\n<dd><p>Cloudflare R2 is an S3-compatible object storage service with zero egress fees. It's perfect for storing and serving media files.<\/p><\/dd>\n<dt id=\"do%20i%20need%20a%20paid%20cloudflare%20plan%3F\"><h3>Do I need a paid Cloudflare plan?<\/h3><\/dt>\n<dd><p>No, R2 storage is available on all Cloudflare plans including Free. You get 10GB storage free per month. Pricing: $0.015\/GB\/month after that.<\/p><\/dd>\n<dt id=\"what%20about%20cloudflare%20image%20transformations%20pricing%3F\"><h3>What about Cloudflare Image Transformations pricing?<\/h3><\/dt>\n<dd><p>First 5,000 transformations per month are free. After that, it's $0.50 per 1,000 transformations. The plugin tracks your usage in the dashboard.<\/p><\/dd>\n<dt id=\"can%20i%20keep%20local%20files%20after%20offloading%3F\"><h3>Can I keep local files after offloading?<\/h3><\/dt>\n<dd><p>Yes, there's an option to keep local files. This is useful for backup or if you need local file access.<\/p><\/dd>\n<dt id=\"what%20happens%20if%20i%20deactivate%20the%20plugin%3F\"><h3>What happens if I deactivate the plugin?<\/h3><\/dt>\n<dd><p>Media URLs will revert to local paths. Your files remain in R2 storage. The plugin stores original local URLs for seamless fallback.<\/p><\/dd>\n<dt id=\"does%20it%20work%20with%20woocommerce%3F\"><h3>Does it work with WooCommerce?<\/h3><\/dt>\n<dd><p>Yes! Full WooCommerce integration for product images, galleries, and thumbnails.<\/p><\/dd>\n<dt id=\"can%20i%20restore%20files%20from%20r2%20to%20local%3F\"><h3>Can I restore files from R2 to local?<\/h3><\/dt>\n<dd><p>Yes, use the \"Restore\" action in Media Library or bulk restore in the Bulk Actions tab.<\/p><\/dd>\n<dt id=\"what%20image%20formats%20are%20supported%20for%20optimization%3F\"><h3>What image formats are supported for optimization?<\/h3><\/dt>\n<dd><p>The plugin supports WebP (recommended) and AVIF conversion. Original format is preserved as fallback.<\/p><\/dd>\n<dt id=\"is%20it%20multisite%20compatible%3F\"><h3>Is it multisite compatible?<\/h3><\/dt>\n<dd><p>Currently designed for single-site installations. Multisite support is planned for future releases.<\/p><\/dd>\n<dt id=\"does%20it%20support%20wp-cli%3F\"><h3>Does it support WP-CLI?<\/h3><\/dt>\n<dd><p>Yes! The plugin includes WP-CLI commands for bulk operations: <code>wp cfr2 status<\/code>, <code>wp cfr2 offload<\/code>, <code>wp cfr2 restore<\/code>, and <code>wp cfr2 free-space<\/code>. All commands support <code>--dry-run<\/code> and <code>--batch-size<\/code> options.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.0.2<\/h4>\n\n<ul>\n<li>Follow-up release for 1.0.1 to correct packaged version metadata in WordPress.org SVN trunk and tag builds.<\/li>\n<li>Added stricter release verification so plugin header <code>Version<\/code>, <code>CFR2_VERSION<\/code>, <code>Stable tag<\/code>, and generated SVN artifacts must match the requested release version before deployment.<\/li>\n<li>Updated release documentation and changelog metadata for the 1.0.2 rollout.<\/li>\n<\/ul>\n\n<h4>1.0.1<\/h4>\n\n<ul>\n<li>Fixed plugin activation to create the full R2\/CDN settings schema instead of legacy placeholder settings.<\/li>\n<li>Added settings normalization and migration so existing installs automatically receive missing keys safely.<\/li>\n<li>Improved validation across settings save, Worker actions, WP-CLI, media actions, and queue processing with clearer configuration errors.<\/li>\n<li>Hardened queue scheduling fallback for sites without Action Scheduler and reduced duplicate queue items in bulk operations.<\/li>\n<li>Fixed Cloudflare zone detection for custom domains, corrected Worker route generation, and cleared CDN availability cache when CDN settings change.<\/li>\n<li>Updated uninstall\/deactivation cleanup to handle current encrypted secrets correctly.<\/li>\n<li>Cleaned up PHPCS violations, repaired PHPMD and pre-commit tooling, refreshed bundled documentation, and added regression tests.<\/li>\n<\/ul>\n\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>Initial release<\/li>\n<li>R2 storage integration with AWS SDK<\/li>\n<li>Automatic and bulk media offload<\/li>\n<li>CDN URL rewriting<\/li>\n<li>Cloudflare Worker auto-deployment<\/li>\n<li>Image optimization (WebP\/AVIF)<\/li>\n<li>Responsive srcset generation<\/li>\n<li>WooCommerce integration<\/li>\n<li>Background queue processing<\/li>\n<li>Rate limiting and security features<\/li>\n<li>Dashboard with usage statistics<\/li>\n<li>WP-CLI commands (status, offload, restore, free-space)<\/li>\n<\/ul>","raw_excerpt":"Offload WordPress media to Cloudflare R2 storage and serve via CDN with automatic image optimization.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/fr-ca.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/279492","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fr-ca.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/fr-ca.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/fr-ca.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=279492"}],"author":[{"embeddable":true,"href":"https:\/\/fr-ca.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/thachpn165"}],"wp:attachment":[{"href":"https:\/\/fr-ca.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=279492"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/fr-ca.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=279492"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/fr-ca.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=279492"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/fr-ca.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=279492"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/fr-ca.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=279492"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/fr-ca.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=279492"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}