next/image is one of Next.js's biggest wins. It automatically:
1import Image from "next/image";
2import logo from "@/public/logo.png";
3
4<Image src={logo} alt="CoachNest" />Local imports include width/height at build time — no dimensions needed.
Whitelist the domain in next.config.ts:
1images: {
2 remotePatterns: [
3 { protocol: "https", hostname: "images.unsplash.com" },
4 { protocol: "https", hostname: "cdn.coachnest.dev" },
5 ],
6},Then provide width/height (or fill):
1<Image
2 src="https://images.unsplash.com/photo-...."
3 alt="Hero"
4 width={1200}
5 height={600}
6/>fill Prop¶For containers where you don't know the dimensions ahead of time:
1<div className="relative aspect-video">
2 <Image
3 src={course.thumbnail}
4 alt={course.title}
5 fill
6 sizes="(max-width: 768px) 100vw, 50vw"
7 className="object-cover"
8 />
9</div>Next.js 16 change:
sizesis now required when usingfill. The build will fail without it.
1<Image
2 src={hero}
3 alt="…"
4 priority
5 sizes="100vw"
6 className="w-full"
7/>priority opts out of lazy loading and adds the image to the preload list.
1<Image src={cover} alt="…" placeholder="blur" />Local imports include a blurDataURL automatically. For remote images, generate one with the plaiceholder library or skip the placeholder.
1<Image src={cover} alt="…" width={1200} height={600} quality={75} />The default quality (75) is the sweet spot. Increase only if you've measured a visual issue.
sharp (a native library). The Docker base image node:20-alpine works; you may need to add apk add vips for some image types.If you don't want Next.js to optimize images at all (e.g., your CDN already does):
1images: { unoptimized: true }| Mistake | Fix |
|---|---|
Using <img> instead of <Image> for app content | Use <Image> — ESLint will warn |
Forgetting sizes with fill | Build will error in Next.js 16 |
| Setting both width/height AND fill | Pick one |
| Loading 4000×3000 images | Always pass sizes so smaller versions are generated |
Marking every image priority | Only the LCP image should be priority |