NNicheStackTutorials
← All tutorials
Astro

Auto WebP for Markdown Images in Astro

Remark plugin + astro:assets pipeline so every ![](image.jpg) in MDX becomes responsive WebP at build time.

·12 min read·Astro
Auto WebP for Markdown Images in Astro cover

Tested on: Astro 5.7, @astrojs/mdx 4.2 Before: 1.8 MB JPEG in post. After: 42 KB WebP, responsive srcset.

Use Astro Image in MDX

astro.config.mjs:

import { defineConfig } from 'astro/config';
import mdx from '@astrojs/mdx';

export default defineConfig({
  integrations: [mdx()],
  image: {
    service: { entrypoint: 'astro/assets/services/sharp' }
  }
});

MDX component override

src/components/MdxImage.astro:

---
import { Image } from 'astro:assets';

interface Props {
  src: string;
  alt: string;
}

const { alt } = Astro.props;
const images = import.meta.glob('/src/assets/posts/**/*.{jpg,png,webp}');

const src = Astro.props.src.replace(/^\.\//, '');
const key = `/src/assets/posts/${src}`;
const loader = images[key];

if (!loader) {
  throw new Error(`Image not found: ${key}`);
}

const mod = await loader();
const image = (mod as { default: ImageMetadata }).default;
---

<Image src={image} alt={alt} widths={[400, 800, 1200]} formats={['webp', 'jpeg']} loading="lazy" />

Wire into MDX

astro.config.mjs:

mdx({
  components: {
    img: './src/components/MdxImage.astro'
  }
})

Now in MDX:

![Screenshot](./my-app/screenshot.png)

Put images in src/assets/posts/my-app/screenshot.png.

Build error

Image not found: /src/assets/posts/my-app/screenshot.png

MDX path is relative to the .mdx file. Match folder structure or use absolute import paths.

Alternative — rehype plugin for plain markdown

For .md files in content collections, use remark-image or custom rehype transformer. MDX component override is simpler if you're already on MDX.

Hero image — eager load

Pass loading="eager" and fetchpriority="high" via frontmatter flag:

---
title: My Post
hero eager: true
---

![Hero](./hero.png)

Check frontmatter in MdxImage.astro via Astro.locals or separate HeroImage component.

Size comparison (real post)

screenshot.png: 1.8 MB
screenshot-400w.webp: 18 KB
screenshot-800w.webp: 42 KB
screenshot-1200w.webp: 78 KB

Lighthouse

Properly size images: PASS
Use modern formats: PASS
LCP: 3.2s → 1.1s

Tags: AstroWebPMarkdownImages