Drop-in next/image-compatible <Image /> for any React app backed by Strapi v5. Responsive srcSet, WebP/AVIF conversion, blur placeholders, and aggressive caching — powered by Sharp.
| Package | Description |
|---|---|
strapi-plugin-next-image |
Strapi v5 plugin — exposes GET /api/next-image via Sharp |
strapi-next-image |
React <Image /> component — drop-in next/image replacement |
- Responsive images — automatic
srcSetandsizesfor every breakpoint - Format negotiation — serves AVIF > WebP > JPEG based on
Acceptheader - Blur placeholders — auto-generated base64 thumbnails with fade-in
- Aggressive caching — file-based cache with configurable TTL, ETags, and
Cache-Control - Animated image support — GIF, WebP, and APNG served untouched
- Priority / preload —
priorityprop injects<link rel="preload">for LCP images - Fill mode — container-relative sizing, just like
next/image - Custom loaders — point the component at any optimization endpoint
- Type-safe — full TypeScript definitions including a
StrapiMediatype guard
npm install strapi-plugin-next-image
npm run buildThe plugin auto-registers /api/next-image and generates blur placeholders for every upload.
npm install strapi-next-imageimport { initializeStrapiImage } from 'strapi-next-image';
import Image from 'strapi-next-image';
// Call once at app entry point — syncs breakpoints from Strapi and sets the loader URL
await initializeStrapiImage('https://cms.example.com');
function Hero({ cover }) {
return (
<Image
src={cover} // StrapiMedia object — width, height, alt, blurDataURL auto-populated
sizes="(max-width: 768px) 100vw, 800px"
fill
priority
style={{ objectFit: 'cover' }}
/>
);
}Pass a StrapiMedia object to src and the component extracts width, height, alt, and blurDataURL automatically. Plain URL strings work too if you supply those props manually.
<Image
src="/uploads/photo.jpg"
alt="A description of the photo"
width={1200}
height={800}
sizes="(max-width: 768px) 100vw, 1200px"
/><Image src={cover} quality={90} priority /><Image src={cover} unoptimized />For CSS background-image or custom <picture> elements:
import { getImageProps } from 'strapi-next-image';
const { props } = getImageProps({ src: cover, alt: 'Hero', sizes: '100vw', fill: true });
// props.srcSet, props.src, props.width, props.height, etc.initializeStrapiImage('https://cms.example.com') configures the global loader — no per-image custom loaders needed. For a one-off override: loader={createStrapiLoader('https://cms.example.com')}.
export default {
'next-image': {
config: {
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
imageSizes: [32, 48, 64, 96, 128, 256, 384],
qualities: [75],
formats: ['image/webp'],
minimumCacheTTL: 14400,
dangerouslyAllowSVG: false,
blurSize: 8,
},
},
};| Option | Default | Description |
|---|---|---|
deviceSizes |
[640, 750, 828, 1080, 1200, 1920, 2048, 3840] |
Viewport breakpoints |
imageSizes |
[32, 48, 64, 96, 128, 256, 384] |
Fixed-width sizes |
qualities |
[75] |
Allowed quality values |
formats |
['image/webp'] |
Output formats |
minimumCacheTTL |
14400 |
Cache lifetime in seconds |
dangerouslyAllowSVG |
false |
Allow SVG passthrough |
blurSize |
8 |
Blur thumbnail width in px |
GET /api/next-image?url=/uploads/file.jpg&w=1080&q=75&f=webp
| Param | Required | Description |
|---|---|---|
url |
Yes | Path starting with /uploads/ |
w |
Yes | Width — must be in deviceSizes or imageSizes |
q |
No | Quality 1–100 (default 75) |
f |
No | Format override (webp, avif) |
git clone https://github.com/edmogeor/strapi-plugin-next-image.git
cd strapi-plugin-next-image
npm install
npm run build --workspaces
npm run test --workspacesThe examples/ directory has a full Strapi + Vite/React stack for manual testing:
npm run dev # starts both Strapi and the frontendOr separately:
cd examples/strapi && npm install && npm run develop
cd examples/frontend && npm install && npm run devVisit http://localhost:1337/admin to upload images, then http://localhost:5173 to see the component in action.
Includes code ported from the Next.js Image component by Vercel, Inc. (MIT). See NOTICE.
