fix(placeholder): rename SVG to bust Cloudflare cache

The new A-monogram placeholder shipped in d8ca8ff was correct in the
deployed container, but Cloudflare was serving the previous cached SVG
(cf-cache-status: HIT, last-modified from this morning) because the
account token doesn't carry Zone:Cache Purge scope, so we couldn't
issue an API purge.

Renaming the file to article-placeholder-v2.svg gives CF a fresh URL
to cache, sidestepping the missing-permission entirely. Updated all
6 referencing files (AppImage fallback, legacy-source FALLBACK_IMAGE
constants, FeaturedBento[FromDb], manufacturers/authors pages).

Old file (cached as the old wordmark) just becomes a dangling asset —
not referenced from anywhere, harmless.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-04 21:44:20 +00:00
parent d8ca8ff3ec
commit 761ebf0cdc
7 changed files with 18 additions and 18 deletions

View File

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -89,7 +89,7 @@ export default function AuthorProfilePage() {
excerpt: a.excerpt || "",
category: a.category || "News",
date: a.date || "",
image: a.image || "/assets/images/article-placeholder.svg",
image: a.image || "/assets/images/article-placeholder-v2.svg",
alt: a.alt || a.title,
readTime: a.readTime || "1 min read",
}));
@@ -275,7 +275,7 @@ export default function AuthorProfilePage() {
>
<div className="img-zoom h-44 overflow-hidden">
<AppImage
src={article.image || "/assets/images/article-placeholder.svg"}
src={article.image || "/assets/images/article-placeholder-v2.svg"}
alt={article.alt}
width={400}
height={176}

View File

@@ -47,77 +47,77 @@ const rotatingStories = [
{
title: "Telestream Expands Its Cloud Services with the Introduction of UP",
category: "BROADCAST",
image: "/assets/images/article-placeholder.svg",
image: "/assets/images/article-placeholder-v2.svg",
alt: "Cloud services infrastructure for broadcast production environments",
slug: "telestream-expands-cloud-services-up",
},
{
title: "Operative Launches AOS Configuration for Digital-First Monetization",
category: "BROADCAST",
image: "/assets/images/article-placeholder.svg",
image: "/assets/images/article-placeholder-v2.svg",
alt: "Digital monetization analytics dashboard for broadcast advertising",
slug: "operative-launches-aos-configuration",
},
{
title: "Calrec Redefines Broadcast Workflows at NAB 2026 with its Most Powerful Audio Lineup Yet",
category: "BROADCAST",
image: "/assets/images/article-placeholder.svg",
image: "/assets/images/article-placeholder-v2.svg",
alt: "Calrec audio mixing console for broadcast production at NAB 2026",
slug: "calrec-redefines-broadcast-workflows-nab-2026",
},
{
title: "Ease Live Powers Interactive Premier Padel Experiences on Red Bull TV as Viewership Surges 30%",
category: "BROADCAST",
image: "/assets/images/article-placeholder.svg",
image: "/assets/images/article-placeholder-v2.svg",
alt: "Interactive sports broadcast experience on streaming platform",
slug: "ease-live-premier-padel-red-bull-tv",
},
{
title: "From Metadata to Meaning: Why Semantic Intelligence Is Media\'s Next Competitive Advantage",
category: "FEATURED",
image: "/assets/images/article-placeholder.svg",
image: "/assets/images/article-placeholder-v2.svg",
alt: "Media metadata intelligence and content analytics visualization",
slug: "from-metadata-to-meaning-semantic-intelligence",
},
{
title: "Mediagenix Title Management Accelerates Content Monetization Through Advanced Semantic Intelligence",
category: "POST PRODUCTION",
image: "/assets/images/article-placeholder.svg",
image: "/assets/images/article-placeholder-v2.svg",
alt: "Content management system for media title management and monetization",
slug: "mediagenix-title-management",
},
{
title: "Emergent Launches Fusion: The \'Interactive Anything\' Platform Transforming Data-Driven Storytelling",
category: "BROADCAST",
image: "/assets/images/article-placeholder.svg",
image: "/assets/images/article-placeholder-v2.svg",
alt: "Interactive data storytelling platform for broadcast and enterprise use",
slug: "emergent-launches-fusion-platform",
},
{
title: "Matrox Video Enables the Next Era of Software-Defined Media Production at NAB 2026",
category: "BROADCAST",
image: "/assets/images/article-placeholder.svg",
image: "/assets/images/article-placeholder-v2.svg",
alt: "Matrox video production hardware and software at NAB 2026 exhibition",
slug: "matrox-video-software-defined-nab-2026",
},
{
title: "Video is King: 2026 Iconik Media Stats Report Finds Video Consumes 64% of Storage Needs",
category: "FEATURED",
image: "/assets/images/article-placeholder.svg",
image: "/assets/images/article-placeholder-v2.svg",
alt: "Video storage statistics and media asset management data visualization",
slug: "video-is-king-2026-iconik-media-stats",
},
{
title: "QuickLink\'s Latest StudioEdge Models to Make North American Debut at NAB 2026",
category: "BROADCAST",
image: "/assets/images/article-placeholder.svg",
image: "/assets/images/article-placeholder-v2.svg",
alt: "QuickLink StudioEdge broadcast production equipment at NAB exhibition",
slug: "quicklink-studioedge-nab-2026",
},
{
title: "Utah Scientific Expands Technology Partner Program With Integrations From Audinate, Bitfocus, and Skaarhoj",
category: "BROADCAST",
image: "/assets/images/article-placeholder.svg",
image: "/assets/images/article-placeholder-v2.svg",
alt: "Broadcast routing and control system technology partner integration",
slug: "utah-scientific-partner-program",
},

View File

@@ -417,7 +417,7 @@ export default async function ManufacturerProfile({
article featured_image → company logo → static placeholder. */}
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src={r.featured_image || company.logo_url || '/assets/images/article-placeholder.svg'}
src={r.featured_image || company.logo_url || '/assets/images/article-placeholder-v2.svg'}
alt=""
className="w-20 h-14 rounded object-cover bg-[#FFFFFF] flex-shrink-0"
loading="lazy"

View File

@@ -63,7 +63,7 @@ export default async function FeaturedBento() {
const heroAd = pickAds("300x600", 1)[0] || null;
function img(r: Row): string {
return r.featured_image ? rewriteLegacyImageUrl(r.featured_image) : "/assets/images/article-placeholder.svg";
return r.featured_image ? rewriteLegacyImageUrl(r.featured_image) : "/assets/images/article-placeholder-v2.svg";
}
return (

View File

@@ -35,7 +35,7 @@ const AppImage = memo(function AppImage({
fill = false,
sizes,
onClick,
fallbackSrc = '/assets/images/article-placeholder.svg',
fallbackSrc = '/assets/images/article-placeholder-v2.svg',
loading = 'lazy',
unoptimized = false,
...props

View File

@@ -49,8 +49,8 @@ interface PersonaJoin {
avatar_url: string | null;
}
const FALLBACK_IMAGE = "/assets/images/article-placeholder.svg";
const REWRITE_FALLBACK_IMAGE = "/assets/images/article-placeholder.svg";
const FALLBACK_IMAGE = "/assets/images/article-placeholder-v2.svg";
const REWRITE_FALLBACK_IMAGE = "/assets/images/article-placeholder-v2.svg";
type Section = Article["section"];
const SECTION_TAGS: Record<Section, string[]> = {