{"id":98051,"date":"2026-10-09T03:02:00","date_gmt":"2026-10-09T07:02:00","guid":{"rendered":"https:\/\/overcentral.com\/en\/?p=98051"},"modified":"2026-09-29T08:02:18","modified_gmt":"2026-09-29T12:02:18","slug":"emdash-media-library-upload-manage-optimize-98051","status":"publish","type":"post","link":"https:\/\/overcentral.com\/en\/emdash-media-library-upload-manage-optimize-98051\/","title":{"rendered":"EmDash Media Library: Upload, Manage, and Optimize Images"},"content":{"rendered":"<p>The media library is where most CMS projects live or die. You upload a hero image. You crop it. You reuse it across a dozen pages. WordPress made this workflow famous \u2014 but it also made it painful. Bloat, versioning nightmares, and storage limits that force you to delete old files.<\/p>\n<p>EmDash takes a different approach. Built on <a href=\"https:\/\/www.cloudflare.com\/products\/r2\/\" target=\"_blank\" rel=\"noopener noreferrer\" data-iacss-external=\"1\">Cloudflare R2<\/a>, the media library separates storage from your server entirely. Images live in blob storage, not in a <code>\/wp-content\/uploads<\/code>codecodecodecode folder next to your code. That changes everything about how you manage, scale, and pay for media.<\/p>\n<p>Let me walk through the exact steps \u2014 upload, manage, optimize \u2014 and show you where EmDash breaks the old mold.<\/p>\n<h2>How to Access the Media Library<\/h2>\n<p>Open your EmDash admin panel. On the left sidebar, click <strong>Media<\/strong> under the Content section.<\/p>\n<p>You&#8217;ll see a grid of all uploaded files. Thumbnails load fast because they&#8217;re served from Cloudflare&#8217;s edge cache, not from a PHP script hitting your database.<\/p>\n<p>The interface is clean. No clutter. Each file shows its name, type, dimensions, and file size. A search bar at the top lets you filter by filename.<\/p>\n<p>Expected outcome: You see every file you&#8217;ve uploaded, sorted by date, with instant thumbnail previews. No pagination lag.<\/p>\n<h2>Uploading Images \u2014 Step by Step<\/h2>\n<h3>Step 1: Click the Upload Button<\/h3>\n<p>In the top-right corner of the Media grid, click <strong>Upload<\/strong>. A file picker opens.<\/p>\n<h3>Step 2: Select Your Files<\/h3>\n<p>Choose one image or multiple. EmDash accepts JPEG, PNG, WebP, GIF, and AVIF. There&#8217;s no hard file-size limit in the CMS itself \u2014 R2 handles large files natively.<\/p>\n<p>Expected outcome: The upload begins immediately. You see a progress bar for each file.<\/p>\n<h3>Step 3: Wait for Edge Processing<\/h3>\n<p>Files upload directly to Cloudflare R2. They don&#8217;t pass through your server. No PHP memory limits, no timeouts. A 10 MB image uploads in seconds.<\/p>\n<p>Expected outcome: Each file appears in the grid with a green checkmark. No server-side processing delay.<\/p>\n<h3>Step 4: Set Alt Text and Metadata<\/h3>\n<p>Click any uploaded image. A side panel opens. Here you can add:<\/p>\n<ul>\n<li><strong>Alt text<\/strong> \u2014 required for accessibility and SEO<\/li>\n<li><strong>Caption<\/strong> \u2014 optional, displayed below the image in some themes<\/li>\n<li><strong>Description<\/strong> \u2014 internal notes, not visible to visitors<\/li>\n<\/ul>\n<p>Expected outcome: Metadata saves instantly. No page reload.<\/p>\n<h3>Step 5: Copy the URL<\/h3>\n<p>In the same side panel, you&#8217;ll find a <strong>Copy URL<\/strong> button. The URL points directly to the R2 bucket, served through Cloudflare&#8217;s CDN.<\/p>\n<p>Expected outcome: You get a public URL that loads fast from any location. No database queries on every request.<\/p>\n<h2>Managing Images<\/h2>\n<h3>Replace an Image Without Breaking Links<\/h3>\n<p>This is one of EmDash&#8217;s best features. Open any image, click <strong>Replace<\/strong>, and upload a new version. The URL stays the same. Every page that references that image updates automatically.<\/p>\n<p>Expected outcome: Old image is replaced. All published pages show the new version. Zero broken links.<\/p>\n<h3>Delete Images<\/h3>\n<p>Select one or multiple images. Click the trash icon. Confirmation dialog appears. Once confirmed, the file is removed from R2.<\/p>\n<p>Expected outcome: File deleted. No orphaned database entries \u2014 EmDash cleans up references automatically.<\/p>\n<h3>Bulk Select<\/h3>\n<p>Hold Shift and click multiple images. Or click the checkbox in the header to select all on the current page. Then apply an action \u2014 delete, download, or add to a collection.<\/p>\n<p>Expected outcome: Batch operations complete in seconds, not minutes.<\/p>\n<h2>Optimization \u2014 What Makes EmDash Different<\/h2>\n<p>WordPress stores images on your server&#8217;s filesystem. Each request to serve an image hits PHP, then the filesystem, then a web server. That&#8217;s three layers of overhead per image.<\/p>\n<p>EmDash stores images in R2, served directly from Cloudflare&#8217;s edge. No PHP involved. No filesystem reads. The CDN caches the image at 330+ locations worldwide.<\/p>\n<p><strong>Zero egress fees.<\/strong> R2 <a href=\"https:\/\/overcentral.com\/en\/rascal-does-not-dream-trailer-release-80139\/\" title=\"Rascal Does Not Dream Drops Trailer for Final Film\" data-iacss-internal=\"1\">does not<\/a> charge you for serving files. If your site gets a traffic spike, your media costs stay flat. WordPress hosting, by contrast, charges for bandwidth \u2014 and overage bills arrive without warning.<\/p>\n<p><strong>No image compression built in yet.<\/strong> EmDash version 0.1 does not include an automatic image optimizer. You should compress images before uploading. Tools like <a href=\"https:\/\/squoosh.app\/\" target=\"_blank\" rel=\"noopener noreferrer\" data-iacss-external=\"1\">Squoosh<\/a>, <a href=\"https:\/\/imageoptim.com\/\" target=\"_blank\" rel=\"noopener noreferrer\" data-iacss-external=\"1\">ImageOptim<\/a>, or a CLI tool like <code>sharp<\/code>codecodecodecode work well.<\/p>\n<p>Expected outcome: Images load 2-3x faster than WordPress-served files. Your hosting bill stays predictable.<\/p>\n<h2>EmDash vs WordPress: Media Library Comparison<\/h2>\n<table class=\"mw-table\">\n<thead>\n<tr>\n<th>Dimension<\/th>\n<th>EmDash (R2)<\/th>\n<th>WordPress (Local Filesystem)<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Storage location<\/td>\n<td>Cloudflare R2 (blob storage)<\/td>\n<td><code>\/wp-content\/uploads<\/code>codecodecodecode on your server<\/td>\n<\/tr>\n<tr>\n<td>Egress fees<\/td>\n<td>Zero<\/td>\n<td>Varies by host \u2014 often $0.10-$0.50\/GB overage<\/td>\n<\/tr>\n<tr>\n<td>Max file size<\/td>\n<td>No hard limit (R2 accepts up to 5 TB per file)<\/td>\n<td>PHP <code>upload_max_filesize<\/code>codecodecodecode limit (typically 2-64 MB)<\/td>\n<\/tr>\n<tr>\n<td>CDN delivery<\/td>\n<td>Built-in (Cloudflare edge)<\/td>\n<td>Requires plugin or separate CDN setup<\/td>\n<\/tr>\n<tr>\n<td>Server load<\/td>\n<td>None \u2014 files served directly from R2<\/td>\n<td>PHP + filesystem read on every request<\/td>\n<\/tr>\n<tr>\n<td>Backup strategy<\/td>\n<td>Replicate R2 bucket to another region<\/td>\n<td>Manual or plugin-based backup of uploads folder<\/td>\n<\/tr>\n<tr>\n<td>URL permanence<\/td>\n<td>Replace file, keep same URL<\/td>\n<td>Replace requires same filename or redirect<\/td>\n<\/tr>\n<tr>\n<td>Thumbnail generation<\/td>\n<td>Manual (no auto-resize yet in v0.1)<\/td>\n<td>Automatic on upload (multiple sizes)<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>Three Best Practices for EmDash Media<\/h2>\n<p><strong>1. Compress before uploading.<\/strong> EmDash does not auto-optimize images yet. Run your images through Squoosh or ImageOptim. Target WebP for modern browsers, JPEG at 80-85% quality for photos. A 2 MB JPEG becomes 300 KB with no visible quality loss.<\/p>\n<p><strong>2. Name files descriptively.<\/strong> EmDash search works on filenames. <code>hero-banner-homepage.webp<\/code>codecodecodecode is searchable. <code>IMG_4921.jpg<\/code>codecodecodecode is not. Rename files before upload.<\/p>\n<p><strong>3. Use alt text on every image.<\/strong> The side panel saves alt text instantly. Search engines read it. Screen readers read it. EmDash surfaces alt text in the REST API, so headless frontends inherit it automatically.<\/p>\n<h2>The One Thing That&#8217;s Missing<\/h2>\n<p>EmDash v0.1 does not generate multiple image sizes on upload. WordPress creates thumbnails, medium, and large versions automatically. EmDash stores only the original file.<\/p>\n<p>For a blog post, that means you serve the full-resolution image even in a 300-pixel-wide sidebar. Not ideal.<\/p>\n<p>The fix: upload images at the exact size you need. Or use a client-side <code><img><\/code>codecodecodecode setup with manually generated variants. The EmDash team will likely add auto-resizing in a future release \u2014 but for now, you control the output.<\/p>\n<p>If you&#8217;re migrating from WordPress, check your theme&#8217;s image sizes. A 1200-pixel-wide featured image works fine on a blog post. A 2400-pixel-wide hero image does not belong in a thumbnail slot.<\/p>\n<p>EmDash&#8217;s media library is simple, fast, and cost-predictable. It trades WordPress&#8217;s auto-resizing convenience for a cleaner architecture and zero egress fees. That trade works well \u2014 if you adjust your upload workflow to match.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The media library is where most CMS projects live or die. You upload a hero image. You crop it. You reuse it across a dozen pages. WordPress made this workflow famous \u2014 but it also made it painful. Bloat, versioning nightmares, and storage limits that force you to delete old files. EmDash takes a different [&hellip;]<\/p>\n","protected":false},"author":7,"featured_media":99798,"comment_status":"closed","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"fifu_image_url":"https:\/\/cards.overcentral.com\/cards\/en\/98051.png","fifu_image_alt":"EmDash Media Library: Upload, Manage, and Optimize Images","footnotes":""},"categories":[31],"tags":[],"class_list":["post-98051","post","type-post","status-publish","format-standard","has-post-thumbnail","category-technology"],"fifu_image_url":"https:\/\/cards.overcentral.com\/cards\/en\/98051.png","fifu_image_alt":"EmDash Media Library: Upload, Manage, and Optimize Images","_links":{"self":[{"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/posts\/98051","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/comments?post=98051"}],"version-history":[{"count":1,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/posts\/98051\/revisions"}],"predecessor-version":[{"id":99799,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/posts\/98051\/revisions\/99799"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/media\/99798"}],"wp:attachment":[{"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/media?parent=98051"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/categories?post=98051"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/tags?post=98051"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}