An image URL often gets copied into more places than anyone expects. It may appear in a website, an application, an email campaign, a product listing, a presentation, and a document that nobody plans to edit again. When the image changes, replacing every reference is slow and easy to get wrong.
The better approach is to give the image a stable identity. The URL points to that identity while the file behind it can move from one revision to the next.
This guide shows how that model works, how to use it in HTML and Next.js, and what to expect from browser and CDN caches after a replacement.
Why ordinary image URLs become a maintenance problem
A conventional storage URL usually describes where a specific file was written. A new file often produces a new key or filename.
https://storage.example.com/campaign/hero-v1.webp
https://storage.example.com/campaign/hero-v2.webp
Publishing the second URL means finding every use of the first one. Changing the bytes at the first URL avoids that work, but it introduces a different problem. Browsers and CDNs may continue serving the cached response because the address still looks identical.
Teams commonly work around this by adding a date, version number, or hash to every filename. That is appropriate for immutable build artifacts, but it is awkward for media that needs a durable public address.
A stable asset URL separates the public address from the stored revision.
https://cdn.steadylink.io/a/campaign-hero
The address identifies the image. A replacement creates another revision and makes it current without changing the address already used by other systems.
Upload the first image
Create a bucket in SteadyLink and upload the image through the dashboard, API, or SteadyLink CLI. When processing and malware scanning finish, the file receives a stable delivery URL.
The URL can be used like any other image source.
<img
src="https://cdn.steadylink.io/a/ASSET_ID"
alt="Campaign artwork"
width="1200"
height="630"
>
The same address can be placed in a CMS, database, email template, mobile application, README, or document. None of those consumers need to know how SteadyLink stores the current revision.
Use the image in Next.js
Allow the SteadyLink delivery hostname in next.config.ts.
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
images: {
remotePatterns: [
{
protocol: "https",
hostname: "cdn.steadylink.io",
pathname: "/a/**",
},
],
},
};
export default nextConfig;
The page can then render the stable URL with the built-in image component.
import Image from "next/image";
const imageUrl = process.env.NEXT_PUBLIC_STEADYLINK_ASSET_URL!;
export default function CampaignHero() {
return (
<Image
src={imageUrl}
alt="Campaign artwork"
width={1200}
height={630}
priority
unoptimized
/>
);
}
The unoptimized property keeps delivery on the SteadyLink URL instead of placing another image cache in front of it. The component does not need to change when a new revision is published. A complete working project is available in the Next.js stable image example.
Replace the file
Open the asset in the dashboard and choose Replace, or use the CLI with the bucket ID and object path.
steadylink replace ./hero-v2.webp \
--bucket YOUR_BUCKET_ID \
--key campaign/hero.webp
SteadyLink uploads the new bytes, validates the file, scans it, and creates a revision. Once that revision is ready, it becomes the file served by the stable URL.
The old revision remains available in the asset history. It can be inspected or restored without creating another public address.
Account for caching
Replacing a file does not mean every existing cache disappears at the same instant. That would remove most of the performance benefit of using a CDN.
The stable SteadyLink URL uses a short cache lifetime. Requests begin receiving the replacement as cached responses expire and the edge checks the current revision again. This creates a small propagation window after a replacement.
When a consumer must receive one exact revision indefinitely, pin the revision in the URL.
https://cdn.steadylink.io/a/ASSET_ID?v=4
Revision-specific responses are immutable and can be cached for much longer. Use the stable URL for content that should follow replacements. Use a pinned URL for audit records, releases, signed documents, or any other consumer that must keep the same bytes.
Choose the right replacement model
Use a stable URL when:
- A logo or campaign image will change over time
- The URL is stored in systems that are difficult to update
- An image appears in emails, documents, or third-party embeds
- You want rollback without republishing links
- Several applications should follow the same current revision
Use a revision-specific URL when:
- The exact bytes form part of a historical record
- A release must remain reproducible
- A cache should retain the file indefinitely
- A consumer should not follow later replacements
These two forms use the same asset history, so a team does not need separate storage workflows for mutable and immutable delivery.
Keep the image URL useful outside your application
A raw image URL is useful for embeds and APIs. A person opening the same image may need more context. Adding ?showcase returns a small HTML page with the image, SteadyLink branding, and a link back to the product.
https://cdn.steadylink.io/a/ASSET_ID?showcase
The showcase page contains no JavaScript. The browser receives the page and loads the original image directly from its stable URL.
Start with one image
Choose an image that has already been replaced manually in several places. Upload it, publish its stable URL, and use that address the next time the artwork changes.
The stable asset URL documentation explains the complete identity and revision model. The delivery documentation covers public, private, and signed links.