Smol for Next.js and React developers

How to Optimize Images for Next.js, Including Static Export

next/image cannot shrink a 14 MB hero sitting in your repo, and its default loader is unsupported in a static export. Smol compresses and resizes your source images on your Mac first, to AVIF, WebP or JPG, so your repo and shipped files stay small.
  • Compress source images before they reach git, one drag for a whole folder
  • Ship AVIF or WebP files directly when next/image is unavailable
  • Resize to the largest width your layout renders, then set quality
  • Nothing is uploaded, so unreleased designs stay on your machine

$29 once per Mac · No subscription · Files never leave your Mac

Smol’s main window in dark and light appearance with an image, a PDF and a video queued and a Compress 3 Files button
By the Smol team9 min read

To optimize images for Next.js, let next/image handle resizing and format selection on a server, and shrink the source files yourself so your repo, build and public folder stay light. With output: 'export' there is no server, so you either add a custom loader or ship files that are already small. Pick the row that matches your situation.

Common Next.js image situations, the problem each one hits, and the Smol setting
What you haveThe problem you hitThe Smol setting
Photos and heroes in public/ or imported, on a server deploymentHuge sources bloat git and slow builds; next/image already makes the delivered sizesCompress, original format, quality 85 to 90, maximum dimension about 2x your widest rendered width
Static export with unoptimized imagesThe default loader is unsupported, so the file you commit is the file users downloadCompress, output AVIF or WebP, quality 60 to 70, maximum dimension at your rendered width
PNG screenshots and illustrationsLarge lossless files in git and in the pageCompress, PNG to WebP or AVIF, quality 65 as a starting point
A repo already heavy with imagesFiles over 50 MiB draw a GitHub warning; over 100 MiB are rejectedBatch compress the folder, then commit the copies

Is next/image enough to optimize images for Next.js?

Often yes. On a server deployment next/image serves correctly sized images, picks a format from the browser’s Accept header (see the Image component reference), lazy loads, and prevents layout shift, per the Next.js images guide. If that is your setup, you do not need another tool in the delivery path. Agencies running many client sites can also see Smol for web agencies.

What it does not do is shrink your repository. It reads the full file you committed and produces smaller variants at request time. A 14 MB source stays 14 MB in git, in every clone and in every CI checkout. This page is about that gap: the source files, and the cases where next/image is switched off. For the page-speed side, see image SEO and page speed.

How do images work with next/image in a static export?

With output: 'export', image optimization using the default loader is not supported. The static export guide lists it under unsupported features, and says to define a custom image loader instead, for example one that builds Cloudinary URLs. The other documented route is the unoptimized prop, which per the Image component reference serves the source “as-is” with no change to quality, size or format.

That second route is where Smol fits. With unoptimized, the bytes you commit are the bytes your visitors download, so the file must already be the right size, quality and format. Compress it to AVIF or WebP at the width you actually render, then point src at it. For the broader loading picture, see image optimization for Core Web Vitals, measured.

Delivery options for images in a Next.js static export
OptionWhat changesWhere Smol fits
Custom loader (next.config.js images.loader)A service resizes per request; you pay or host itTrim the originals you upload to it
unoptimized prop or configFiles are served exactly as committedProduce the final AVIF, WebP or JPG with Smol
Plain <img> or CSS backgroundNo component, no srcset; you control everythingSame: Smol output is the shipped file

One limit to say out loud: Smol produces one size per run. It does not generate a set of responsive widths from one image, and the default output name is the same for every run (name_compressed.ext). If you need 640, 1200 and 1920 pixel versions for an srcset, that is three runs with renaming, or a build script. For one well-chosen size per image, a single run is enough.

Should I use AVIF in Next.js, and how?

Yes for most photographs, with a fallback. The Next.js docs say AVIF “generally takes 50% longer to encode but it compresses 20% smaller compared to WebP”, and that when you enable both formats, AVIF is preferred for browsers that support it with WebP as the fallback. To enable it on a server deployment, set images.formats to ['image/avif', 'image/webp']. The default is WebP only. Read the The same Image component reference notes that each format is cached separately, which raises storage needs.

For a static export, AVIF means committing the AVIF file. Smol’s own measurements on the benchmark page show the size of the opportunity on 24 small (768 × 512) test photos: AVIF needed 22 to 26% fewer bytes than the best JPEG at the same SSIMULACRA2 score, and compressing those photos from PNG to AVIF at quality 65 saved 92.1%. Camera-size files and illustrations will differ, so judge each by eye. Two honest caveats: the test set is small film photographs, and a browser that cannot decode AVIF needs a fallback in your markup, such as a <picture> element. The AVIF converter page covers the format itself.

How do I keep public folder images and my repo small?

Compress before you commit, because git keeps every version forever. Files in public are served from the site root, and statically imported images get width, height and a blurDataURL automatically, per the images guide. Neither feature shrinks the file. GitHub warns above 50 MiB, rejects above 100 MiB per file, and suggests repositories stay ideally under 1 GB.

Hosts have their own ceilings. Cloudflare Pages allows 25 MiB per asset and 20,000 files per site on the Free plan, which matters when an export copies everything in public. A folder of originals straight from a designer can break a deploy long before it breaks a page.

Once a large file is committed, compressing it later does not remove it from history. Our guide to compressing images before you commit explains why, and that is the reason to make Smol the step between the designer’s export and git add.

Which Smol settings should I use for Next.js images?

Choose by who does the final optimization. Smol’s defaults are quality 75, metadata stripped, and images resized to fit inside 2000 × 2000 pixels unless you change it. Quality numbers below are starting points to check by eye, not guarantees.

Smol settings for Next.js and React image assets (Compress operation)
AssetOutput formatQuality (starting point)Maximum dimension
Hero or full-bleed photo, optimizer runsOriginal format85 to 90About 2x the widest rendered width
Hero or full-bleed photo, shipped as-isAVIF (WebP fallback)60 to 70The widest rendered width
Card, thumbnail or avatarWebP or AVIF65 to 75Rendered size, or 2x for high-density screens
PNG screenshotWebP or AVIF65Rendered width
Open Graph or social imageJPG75Whatever the platform asks for

Quality belongs to the Compress operation, not Convert, so choose the output format inside a compress job. Resize modes are fit (stays inside the box), fill (covers the box and crops, with no control over what is cropped), and width or height. For layout-safe output, use fit or width. Smol keeps the original when a compression would make the file larger, and by default writes a copy next to it.

What is the workflow from design export to commit?

  1. Find the widest rendered width

    Check the largest size the image displays at in your layout, in CSS pixels. Double it only if you serve high-density screens.

  2. Drag the folder into Smol

    Whole folders and mixed types are fine. Set the output format and quality from the table above.

  3. Set the maximum dimension

    Use the width from step 1 in fit mode. Leave the 2000 px default only if your layout needs it.

  4. Check the result by eye

    Open the copies beside the originals at the size users see. Raise quality if gradients band or text fringes.

  5. Replace the sources and commit

    Move the _compressed copies into public or your assets folder, drop the suffix, and commit. The originals stay wherever you keep them.

Save the settings as a preset so the next export is one drag. Presets live on that Mac, so a team agrees the numbers in the README and recreates the preset on each machine.

What do React and Next.js developers use today?

Free and built-in options come first because they are often enough.

Ways to optimize images for a Next.js project
ToolGood forLimit
next/image default loaderAutomatic sizes, formats and lazy loading on a serverUnsupported in a static export; does not shrink the repo
Custom loader plus a serviceStatic exports that still want on-demand resizingAn external service in the delivery path
sips (built into macOS)Quick resizes in a shell loopVery fast, but few controls
ImageOptimLossless trimming of JPEG and PNGGentle by default; smaller gains unless lossy mode is on
A build script in CIAutomatic variants on every buildYou write and maintain it
SmolFolders of sources to AVIF, WebP or JPG on your Mac, with a quality settingManual step; one size per run; macOS only

For a fuller look at one-off methods, see every Mac compression method compared, and image optimization for web developers. If you need compression on a server instead, the Smol API exists for that.

When is Smol the wrong tool for Next.js images?

  • You need responsive sets or on-demand variants. Smol makes one size per run. A loader, a service or a build script generates widths automatically.
  • Your pipeline runs on Linux CI. Smol is a Mac app. Use an image library in the build for automation.
  • You need pixel-identical output. Smol has no lossless mode and always re-encodes. ImageOptim’s lossless setting is the answer there.
  • Your images are SVG. Smol does not handle SVG, and next/image serves SVG without optimization anyway.
  • The project is small and next/image already covers it. If every source is under a few hundred KB, skip the extra step.

Speed note

Smol is not the fastest option: 24 small images take about 7 seconds, where a sips loop takes under one. It is a quality-first step you run before commit, not a hot path.

Frequently asked questions

How do I optimize images for Next.js?

Use next/image for delivery, which serves sized, lazy-loaded images in WebP by default, and shrink the source files before you commit them. Resize to about the widest width you render, then set quality. In a static export, compress to AVIF or WebP yourself, because the default loader is unsupported and unoptimized images ship as committed.

Does next/image work with a static export?

Not with the default loader. The Next.js static export guide lists default-loader image optimization as unsupported and says to define a custom loader in next.config.js, such as one for Cloudinary. The other route is the unoptimized prop, which serves the source file as-is, so the file you commit must already be small.

How do I enable AVIF in Next.js?

Set images.formats to ['image/avif', 'image/webp'] in next.config.js on a server deployment. The docs note AVIF generally takes 50% longer to encode but compresses 20% smaller than WebP, and that each format is cached separately. In a static export, commit AVIF files yourself and keep a fallback for browsers that cannot decode them.

How do I reduce the image size of my repo?

Compress before you commit, since git keeps every version. GitHub warns above 50 MiB per file and rejects above 100 MiB, and suggests repositories stay ideally under 1 GB. Batch compress your images folder in Smol, replace the originals with the smaller copies, and commit. Later compression does not remove old versions from history.

Should public folder images be compressed?

Yes, whenever they are served as-is. Files in public are delivered from the site root without changes, so their size is what users download. If next/image processes them, compress lightly (quality 85 to 90) so the optimizer still has detail. If they ship unoptimized, pick the final format and quality yourself and check the result.

Can Smol generate srcset sizes for Next.js?

No. Smol produces one size per run, and the default output name repeats, so several widths of one image need separate runs and renaming. For automatic responsive sets, use next/image with a server or custom loader, or a build script. Smol suits one well-chosen size per image and shrinking sources before git.

Keep reading

Smol for other teams