From harness-claude
Optimizes images in Astro projects at build time using astro:assets, Image, and Picture components. Generates WebP/AVIF, enforces alt text, handles remote images, prevents layout shift with responsive srcsets.
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeThis skill uses the workspace's default tool permissions.
> Use `astro:assets` and the `<Image />` component to automatically optimize images at build time — enforcing `alt` text, generating WebP/AVIF, and preventing layout shift.
Optimizes images in Next.js apps with next/image for automatic sizing, modern formats (WebP/AVIF), lazy loading, and blur placeholders. Improves LCP/CLS via priority and sizes props.
Designs responsive image pipelines with srcset, AVIF/WebP formats, lazy loading, and sizes queries. Generates code for Next.js, Nuxt, Blazor, vanilla HTML/CSS.
Optimizes web images using WebP/AVIF formats, responsive srcset/picture elements, lazy loading, and Sharp for Node.js. Improves page loads, responsive images, production assets.
Share bugs, ideas, or general feedback.
Use
astro:assetsand the<Image />component to automatically optimize images at build time — enforcingalttext, generating WebP/AVIF, and preventing layout shift.
<Picture />getImage() for programmatic image optimization in API endpoints or og:image generationwidth/height dimensionssrc/ using a static import. Astro processes these at build time and infers dimensions automatically:---
import { Image } from 'astro:assets';
import heroImage from '../assets/hero.jpg';
---
<!-- Astro infers width, height, and converts to WebP by default -->
<Image src={heroImage} alt="A mountain at sunrise" />
<Image /> for single-format optimized images. Required props are src and alt. Optional props control the output:<Image
src={heroImage}
alt="Hero"
width={1200} <!-- override inferred width -->
height={630} <!-- override inferred height -->
format="avif" <!-- webp (default), avif, png, jpg -->
quality={80} <!-- 1-100 or 'low' | 'mid' | 'high' | 'max' -->
loading="eager" <!-- lazy (default) or eager -->
decoding="async"
class="hero-img"
/>
<Picture /> for responsive images that serve different formats and sizes based on browser support and viewport:---
import { Picture } from 'astro:assets';
import photo from '../assets/photo.jpg';
---
<Picture
src={photo}
alt="Team photo"
widths={[400, 800, 1200]}
sizes="(max-width: 600px) 400px, (max-width: 900px) 800px, 1200px"
formats={['avif', 'webp']}
fallbackFormat="jpg"
/>
image.remotePatterns in astro.config.mjs. Astro will refuse to process remote images from unlisted hostnames:// astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
image: {
remotePatterns: [
{ protocol: 'https', hostname: 'images.unsplash.com' },
{ protocol: 'https', hostname: '**.cloudinary.com' },
],
},
});
<Image /> with explicit width, height, and inferSize (when dimensions cannot be known ahead of time):<!-- Known dimensions — preferred -->
<Image src="https://images.unsplash.com/photo-abc" alt="..." width={800} height={600} />
<!-- Unknown dimensions — fetches headers to infer size (build-time cost) -->
<Image src={remoteUrl} alt="..." inferSize />
getImage() for programmatic optimization outside of templates — useful for og:image endpoints or generating image URLs for use in CSS:// src/pages/api/og.ts
import { getImage } from 'astro:assets';
import ogBackground from '../assets/og-bg.png';
export const GET = async () => {
const optimized = await getImage({
src: ogBackground,
format: 'png',
width: 1200,
height: 630,
});
// optimized.src — the final URL path
// optimized.attributes — width, height, etc.
return new Response(`<img src="${optimized.src}" />`);
};
image() schema helper to process frontmatter image paths through the optimizer:// src/content/config.ts
import { defineCollection, z } from 'astro:content';
const blog = defineCollection({
schema: ({ image }) =>
z.object({
title: z.string(),
cover: image(), // validates path and enables optimization
}),
});
---
// src/pages/blog/[slug].astro
import { Image } from 'astro:assets';
const { post } = Astro.props;
---
<Image src={post.data.cover} alt={post.data.title} width={1200} height={630} />
astro.config.mjs. Astro uses Sharp by default in Node environments. For Cloudflare or edge deployments, switch to the no-op service and rely on the CDN:import { defineConfig, passthroughImageService } from 'astro/config';
export default defineConfig({
image: {
service: passthroughImageService(), // no optimization, pass through as-is
},
});
Astro's image optimization pipeline is powered by Sharp (Node.js) or the browser's image decoding APIs (depending on deployment target). The <Image /> component enforces several best practices at compile time: alt is required (missing it is a build error), and Astro always adds explicit width and height attributes to prevent layout shift (CLS).
Format selection strategy:
webp — best default: ~30% smaller than JPEG, universal browser supportavif — best compression (~50% smaller than JPEG) but slower to encode at build timepng — use only for images that need transparency<Picture /> with formats={['avif', 'webp']} and fallbackFormat="jpg" to serve the best format each browser supportsLocal vs. remote image processing:
Local images (import hero from './hero.jpg') are processed at build time — the optimized file is written to dist/_astro/. Remote images are fetched during the build (SSG) or on-demand (SSR) and cached. In SSR, remote image optimization happens per-request unless you configure a CDN or caching layer.
inferSize trade-offs:
When inferSize is used on a remote image, Astro makes an HTTP HEAD request during the build to read the Content-Length or decodes the image header to determine dimensions. This adds build time proportional to the number of inferSize images. Prefer explicit width and height when the dimensions are known.
Image service configuration for edge deployments:
Sharp is a native Node.js module — it does not work on Cloudflare Workers or Vercel Edge Runtime. For edge deployments use passthroughImageService() and offload optimization to Cloudflare Image Resizing, Vercel Image Optimization, or Imgix.
Content Security Policy:
When using remote images, your CSP img-src directive must allow the remote origin. The optimized image URL will be an Astro-proxied URL in SSR mode, so only 'self' may be needed depending on configuration.
https://docs.astro.build/en/guides/images