Fixing Image Loading Issues on Netlify with netlify.toml Configuration

2026/08/196 min read
bookmark this

Table of Contents

  1. Introduction
  2. Understanding the Image Loading Issue
  3. What is netlify.toml?
  4. Why Image Optimization Fails on Netlify
  5. Solution: Disable Image Optimization
  6. Setting Up netlify.toml
  7. HTTP to HTTPS Redirect Configuration
  8. Complete netlify.toml Example
  9. Deploying to Netlify
  10. Conclusion

Introduction

Deploying a Next.js application to Netlify can be smooth, but you might encounter an unexpected issue: images fail to load in production even though they work perfectly locally and on Vercel. This typically happens because of how Next.js handles image optimization and how Netlify processes serverless functions. In this guide, we'll explore the root cause, understand the netlify.toml configuration file, and implement a complete solution including HTTPS redirects.

Understanding the Image Loading Issue

When you deploy your Next.js application to Netlify, you might notice images appearing broken or failing to load. Looking at the browser's Network tab, you'll see requests like:

/_next/image?url=https%3A%2F%2Fpicsum.photos%2Fseed%2Fimage%2F360%2F160&w=640&q=75

These requests return 404 errors or fail silently, even though the external image URL (like picsum.photos or unsplash.com) is valid and accessible.

What is netlify.toml?

netlify.toml is Netlify's configuration file that allows you to define build settings, environment variables, redirects, headers, functions, and other deployment behaviors. It's similar to other infrastructure-as-code files like docker-compose.yml or package.json.

Key purposes of netlify.toml:

  • Define build commands and publish directory
  • Configure environment variables
  • Set up redirects and URL rewriting
  • Add HTTP headers (security, caching, CORS)
  • Configure serverless functions
  • Define custom error pages

Unlike Vercel (which auto-detects Next.js configuration), Netlify requires explicit configuration for optimal Next.js support.

Why Image Optimization Fails on Netlify

Next.js Image Component includes built-in image optimization via the /_next/image API endpoint. This works by:

  1. Accepting an external image URL
  2. Downloading and optimizing the image on-the-fly
  3. Serving it in optimized formats (WebP, AVIF)

However:

  • Vercel: Has native support for Next.js Image Optimization as a built-in service ✅
  • Netlify: Does NOT have a built-in Image Optimization API. The /_next/image endpoint doesn't work because Netlify can't run the image processing logic ❌

When Netlify tries to handle the /_next/image request, it either:

  • Returns a 404 (endpoint not found)
  • Times out (no handler)
  • Returns an error (serverless function failure)

Solution: Disable Image Optimization

The fix is to disable Next.js Image Optimization when building for Netlify. This tells Next.js to serve images directly from their source URLs without processing.

Step 1: Update next.config.js

Add environment variable detection and disable optimization:

const isNetlify = process.env.NETLIFY === 'true';

const nextConfig = {
  env: {
    // Your existing env vars
  },
  images: {
    unoptimized: isNetlify, // Disable optimization on Netlify
    domains: ['images.unsplash.com', 'picsum.photos', 'cdn.countryflags.com'],
  },
  // ... rest of config
};

module.exports = nextConfig;

Important: NETLIFY is a built-in environment variable that Netlify automatically sets to 'true' during builds. You don't need to manually configure it—it's provided for free by Netlify. This makes detection seamless:

  • ✅ On Netlify builds: process.env.NETLIFY === 'true' (automatic)
  • ✅ On Vercel/local: process.env.NETLIFY is undefined → images use optimization
  • ✅ The same codebase works on both platforms without manual setup

Setting Up netlify.toml

Create a netlify.toml file in your project root. This tells Netlify how to build and serve your Next.js app.

Basic Configuration

[build]
  command = "npm run build"
  publish = ".next"

[functions]
  external_node_modules = ["sharp"]

Explanation:

  • [build]: Defines how Netlify builds your project
    • command = "npm run build": Runs your Next.js build
    • publish = ".next": Publishes the .next directory (Next.js output)
  • [functions]: Serverless function configuration
    • external_node_modules = ["sharp"]: Allows the sharp library (image processing) if needed

HTTP to HTTPS Redirect Configuration

Modern web standards require HTTPS. You can enforce this at the Netlify level using netlify.toml:

[[redirects]]
  from = "http://*"
  to = "https://:splat"
  status = 301
  force = true

How it works:

  • from = "http://*": Matches all HTTP URLs (wildcard *)
  • to = "https://:splat": Redirects to HTTPS, preserving the path (:splat is Netlify's placeholder)
  • status = 301: Permanent redirect (helps SEO)
  • force = true: Forces redirect even if a file exists at that path

Example:

  • http://example.com/blog/post-1https://example.com/blog/post-1 (path preserved)

Complete netlify.toml Example

Here's a production-ready configuration with security headers:

# Netlify configuration for Next.js application

[build]
  command = "npm run build"
  publish = ".next"

[functions]
  external_node_modules = ["sharp"]

# Redirect HTTP to HTTPS (permanent redirect)
[[redirects]]
  from = "http://*"
  to = "https://:splat"
  status = 301
  force = true

# Security headers
[[headers]]
  for = "/*"
  [headers.values]
    # Enable HTTPS everywhere and HSTS (strict transport security)
    Strict-Transport-Security = "max-age=31536000; includeSubDomains; preload"
    # Prevent clickjacking attacks
    X-Frame-Options = "DENY"
    # Prevent MIME type sniffing
    X-Content-Type-Options = "nosniff"
    # Enable browser XSS protection
    X-XSS-Protection = "1; mode=block"

# Cache static assets longer (optional)
[[headers]]
  for = "/_next/static/*"
  [headers.values]
    Cache-Control = "public, max-age=31536000, immutable"

# Custom error page (optional)
[[redirects]]
  from = "/*"
  to = "/404.html"
  status = 404

Deploying to Netlify

Once you have netlify.toml ready, follow these steps:

Option 1: Using Netlify UI

  1. Push your code to GitHub
  2. Connect your repository to Netlify
  3. Deploy (that's it! Netlify automatically handles the rest)

No manual environment variable setup needed. Netlify automatically sets NETLIFY=true during builds.

Option 2: Using Netlify CLI

# Install Netlify CLI
npm install -g netlify-cli

# Deploy
netlify deploy --prod

Netlify will automatically:

  • Detect your netlify.toml configuration
  • Set the NETLIFY environment variable to 'true'
  • Build your Next.js app with image optimization disabled

Verify Configuration

After deployment:

  1. Check images load: Visit your site and verify all images render correctly
  2. Test HTTPS redirect: Visit http://example.com → should redirect to https://example.com
  3. Inspect headers: Use browser DevTools → Network tab → check response headers for security directives

Conclusion

By understanding how Next.js Image Optimization works and Netlify's limitations, you can configure your application to work seamlessly across different platforms. The netlify.toml file is your gateway to fine-tuning deployment behavior, from disabling image optimization to enforcing HTTPS.

Key takeaways:

  • ✅ Disable image optimization on Netlify using unoptimized: isNetlify in next.config.js
  • ✅ Use netlify.toml to configure build settings, redirects, and security headers
  • ✅ Enforce HTTPS redirects for better security and SEO
  • ✅ Test thoroughly before pushing to production

With this setup, your Next.js blog will work reliably on Netlify with all images loading correctly and your site protected by modern security standards.