Jakob SEO
Back to blog
Performance//6 min read

Serving optimized images locally: a workflow for performance and SEO

Images are usually the heaviest part of a page. Here is a pipeline that keeps the authoring convenience of a cloud CDN but serves aggressively optimized, locally-hosted images at runtime — no third-party DNS, no external latency.

Authoring

Upload high-res sources to a cloud image service.

Build

Sync pulls each asset, transformed, into public/images.

Runtime

Served locally from your own origin — no third-party DNS.

Applied on the way down

f_webpq_auto:lowc_limit,w_2400ar_3:4 · _mobile

If you care about performance, you already know that images are usually the heaviest part of any web page. Cloud-based image CDNs are wonderfully convenient, but relying on them at runtime introduces external DNS lookups, the occasional latency spike, and a third-party dependency between your visitor and your content.

I prefer to keep an application self-contained. Rather than pinging an external server every time someone loads a page, I built a pipeline that gives me the authoring convenience of a cloud CDN but serves aggressively optimized, locally-hosted images at runtime. Here is how it manages, minimizes, and serves static images for fast loads and better SEO.

The architecture: best of both worlds

The workflow is split into two phases: authoring and building. For authoring I use a cloud image service as a staging ground where I upload high-resolution source files. But the source code never links to that service directly. A synchronization step pulls the images into the local public/images directory before deployment, so the running site only ever serves files from its own origin.

The synchronization script

The heart of the system is a dependency-free Python script. By relying only on the standard library (urllib for the HTTP calls, hashlib for hashing), it stays lightweight and runs straight from npm without a Python virtual environment. It talks to the image service’s admin API and, for each asset, requests a transformed version before downloading it:

  • Format conversion: every image is forced into the efficient WebP format (f_webp).
  • Aggressive compression: q_auto:low cuts file size hard without artifacts the eye actually notices.
  • Dimension capping: c_limit,w_2400,h_2400 makes sure no massive original ever slips into the repository.

Automatic mobile cropping

Responsive design is not only about CSS — it is about sending the right bytes to the right device. For hero and header images the sync step generates a dedicated mobile crop, requesting a 3:4 aspect ratio (ar_3:4) at 800px wide and appending _mobile to the filename. Mobile visitors stop downloading desktop-sized images only to have the browser scale them down, which directly improves Largest Contentful Paint.

Smart reference updating

Asset names change when optimizations are tweaked or files are reorganized upstream, and managing those local paths by hand would be a nightmare. So a companion Node script computes the SHA-256 hash of each image and matches it against a local JSON manifest.

When an image is renamed or updated, the hash still matches, so the tooling can traverse the TypeScript content files under src/content and safely rewrite every reference to point at the new local path. No broken links, no missing assets, and zero manual find-and-replace.

Why this matters for SEO

Search engines reward user experience, and speed is a big part of it. By statically serving minimized images from the same origin as the HTML, the browser skips the DNS resolution and TLS negotiation an external CDN would require.

  • Faster connections: everything is served from one origin, so there is no extra handshake per asset host.
  • Predictable caching: because the images are versioned and stored locally, you can apply aggressive, immutable Cache-Control headers at the edge.
  • No layout shifts: the sync records exact width and height, so the frontend can reserve the right space before the image loads and avoid Cumulative Layout Shift.

The takeaway

It takes a little upfront engineering, but the result is a site that runs like a static binary: the rich image management of the cloud at authoring time, and the privacy, control, and raw speed of local files at runtime. If you want to push a site’s performance to the limit, bringing your assets in-house is one of the highest-leverage moves available.