The metal roofing blog post featured image was returning 404 because the public/images/ directory was not being copied to dist/images/ during the build process.
The Vite config's manualPublicCopyPlugin was copying several specific directories (social-proof, projects, case-studies, downloads) but was missing the images/ directory.
Updated vite.config.ts to include the images/ directory in the build copy process (lines 149-169):
// Copy images directory (blog featured images, etc.)
const imagesSrc = path.resolve(publicDir, 'images');
const imagesDest = path.resolve(distDir, 'images');
if (fs.existsSync(imagesSrc)) {
if (!fs.existsSync(imagesDest)) {
fs.mkdirSync(imagesDest, { recursive: true });
}
const imagesFiles = fs.readdirSync(imagesSrc);
imagesFiles.forEach(file => {
const src = path.resolve(imagesSrc, file);
const dest = path.resolve(imagesDest, file);
try {
if (fs.statSync(src).isFile()) {
fs.copyFileSync(src, dest);
console.log(`Copied images/${file}`);
}
} catch (error) {
console.warn(`Skipped images/${file}: ${error.message}`);
}
});
}✅ Image file exists: public/images/metal-roofing-standing-seam-featured.webp (199.69 KB)
✅ Image copied to dist: dist/images/metal-roofing-standing-seam-featured.webp
✅ Database record updated: featured_image = '/images/metal-roofing-standing-seam-featured.webp'
✅ Build successful with images directory copy
- Slug:
metal-roofing-south-florida-what-homeowners-need-to-know - Title: "Metal Roofing in South Florida: What Every Homeowner Needs to Know Before Signing a Contract"
- Featured Image:
/images/metal-roofing-standing-seam-featured.webp - Image Specs: 1200x1600px, WebP format, 199.69 KB
The featured image will now load properly on:
- Blog post page
- Blog index/listing pages
- Any social media shares (Open Graph)
The fix applies to all future blog post images added to public/images/.