Next.js

Next.js RemotePatterns with Supabase Images: A Safe Setup Guide

12 min read
Next.jsSupabaseWeb Development

Next.js RemotePatterns with Supabase Images: A Safe Setup Guide

July 15, 202612 min read read

Configure Next.js Image remotePatterns for Supabase Storage without unsafe wildcards, including public, transformed and signed URL cases.

Read the full article
Next.js RemotePatterns with Supabase Images: A Safe Setup Guide

When Next.js rejects a Supabase image with an “unconfigured host” error, the safe fix is not to allow every remote URL. It is to describe the exact storage origin and path your application expects.

The details matter because Supabase can serve public objects, signed URLs and transformed images from different paths. Next.js also treats protocol, hostname, port, pathname and search parameters as parts of the match.

This guide covers the common configurations and the security decisions behind them.

Why Next.js blocks the URL

The Image component optimises remote images through your application. Next.js requires an explicit allowlist so an attacker cannot make your server fetch arbitrary origins.

According to the current Next.js Image documentation, remote image URLs should be matched with remotePatterns. The rules can be precise about protocol, hostname, port, path and query string.

If any configured part does not match exactly, the image is rejected. Typical mismatches include:

  • allowing http while the URL uses https;
  • using the wrong Supabase project hostname;
  • allowing the object path while the URL uses the render path;
  • including an empty search rule while the image has a signed query string;
  • configuring one bucket path but requesting another;
  • changing next.config without restarting the development server.

Public Supabase Storage objects

A public object URL normally follows this shape:

https://your-project.supabase.co/storage/v1/object/public/your-bucket/path/image.jpg

Use the exact project hostname and narrow the path to the intended bucket:

const nextConfig = { images: { remotePatterns: [ { protocol: 'https', hostname: 'your-project.supabase.co', port: '', pathname: '/storage/v1/object/public/your-bucket/**', search: '', }, ], }, }

export default nextConfig

The double wildcard at the end permits nested object paths inside that bucket. It does not permit another hostname or an unrelated Supabase API path.

The empty search value disallows query parameters. That is appropriate when public object URLs should be stable and query-free. Remove or change it only after deciding which query parameters are necessary.

Supabase's getPublicUrl reference notes that the bucket must be public for the URL to render successfully. Generating a public URL does not bypass bucket access controls.

Transformed public images

Supabase image transformation uses a render path rather than the ordinary object path. A public transformed URL can follow this shape:

https://your-project.supabase.co/storage/v1/render/image/public/your-bucket/path/image.jpg?width=800&quality=80

If your application uses that service, add a separate pattern:

const nextConfig = { images: { remotePatterns: [ { protocol: 'https', hostname: 'your-project.supabase.co', port: '', pathname: '/storage/v1/render/image/public/your-bucket/**', }, ], }, }

Omitting search means query strings can match, so use this only where the application is expected to generate transformation parameters. A stricter application can generate a controlled set of URLs in server code instead of accepting arbitrary user-provided sources.

Supabase's image transformation guidance explains the public and signed transformation routes and current plan availability.

Do you need both Next.js and Supabase optimisation?

Often, no. If a Supabase transformation URL is then passed through the default Next.js optimiser, two systems may perform overlapping work.

Choose an architecture deliberately:

Next.js optimises the original

Use the public object path as the Image source. Next.js requests and caches responsive variants. This keeps width selection in the application but consumes the application's image-optimisation resources.

Supabase serves a transformed image

Generate the required transformation on Supabase. If you have already selected the final dimensions and format strategy, consider whether the Next.js Image component should use a custom loader or be marked unoptimised for that source.

A dedicated image CDN handles variants

Use a custom loader and a tightly controlled CDN origin. Document who owns transformation, signing and cache invalidation.

Avoid paying the latency and cost of two optimisers without a measured reason.

Signed URLs need a different decision

Private buckets commonly use time-limited signed URLs with query parameters. Those parameters are part of the access mechanism. An empty search rule will reject them, while a broad pattern may allow many possible queries.

There is also an architectural concern: Next.js image optimisation fetches the remote source server-side and, as its documentation notes, does not forward arbitrary authentication headers. A signed URL can work because the signature travels in the URL, but caching and expiry must be designed carefully.

For sensitive or user-specific media, consider:

  • generating the signed URL on the server;
  • limiting its lifetime to the actual use case;
  • never exposing a service-role key;
  • using a server route that enforces application authorisation;
  • deciding whether the optimiser may cache beyond the source URL's intended lifetime;
  • using an ordinary image element or unoptimised Image where that boundary is clearer.

Supabase states that transformation parameters for a signed transformed URL cannot be changed after signing. Generate the correct transformation when the URL is created.

Avoid dangerous wildcard patterns

This is too broad for most applications:

{ protocol: 'https', hostname: '**', pathname: '/**', }

It removes much of the protection remotePatterns is meant to provide.

Prefer:

  • one exact Supabase project hostname;
  • one exact bucket prefix;
  • separate entries for object and render routes;
  • explicit query-string handling;
  • server-controlled source construction.

If you have several environments, enumerate their exact hostnames using environment-aware configuration. Do not permit every Supabase project on the internet for convenience.

Configure dimensions and responsive behaviour

Remote images do not provide dimensions to Next.js at build time. Supply width and height, or use fill inside a container with a defined aspect ratio.

Guest room with step-free access beside the bed

Width and height reserve layout space; they do not force the rendered CSS size. The sizes attribute tells the browser how much viewport width the image will occupy so it can select a suitable candidate.

Write alternative text for the image's purpose. Decorative images should use an empty alt value rather than repeating nearby text.

For broader image-performance decisions, see our Next.js image optimisation guide.

A safe URL-construction pattern

Do not accept a complete remote image URL from an untrusted client and pass it straight to Image. Store a controlled object path or key, then construct the URL using trusted server configuration.

Validate that:

  • the bucket is one the application uses;
  • the path contains no unexpected traversal or API route;
  • the requested object belongs to the current tenant or record;
  • the URL is public or appropriately signed;
  • the database record and storage object lifecycle stay in sync.

The hostname allowlist protects the fetch origin. It does not prove that the current user is entitled to see every object on that origin.

Troubleshooting checklist

“Unconfigured host”

Compare the actual URL character by character with protocol and hostname. Confirm the configuration file is loaded and restart the dev server.

Host matches but the image is still rejected

Check the pathname. Public objects use /storage/v1/object/public/, while transformed images use /storage/v1/render/image/public/. Verify the bucket segment and wildcard placement.

Signed URL fails

Inspect the search configuration and expiry. Confirm the URL works directly for an authorised user. Decide whether optimisation caching is compatible with the signed-resource policy.

Image returns 400 or 404

Test the source URL directly. Confirm object path, case, bucket visibility and transformation availability. A matching Next.js pattern cannot make a missing or private object public.

Layout shifts or the wrong image is downloaded

Provide accurate intrinsic dimensions or a stable fill container, then set sizes to reflect the actual layout. Inspect the generated srcset and the rendered CSS width.

Changes work locally but not in production

Verify that the production build used the new next.config, the correct project hostname and the same environment variables. Treat configuration changes as build-time deployment changes.

Production checklist

  • Exact HTTPS Supabase hostnames are listed.
  • Paths are narrowed to the required bucket and route.
  • Query parameters are explicitly allowed or forbidden.
  • Private media has an application authorisation boundary.
  • Width, height or a stable fill container is supplied.
  • sizes reflects the real responsive layout.
  • Alternative text is meaningful or intentionally empty.
  • Only one optimisation layer performs each transformation.
  • Development and production URLs are tested separately.

The bottom line

RemotePatterns should describe a small trust boundary: this protocol, this storage host, this bucket route and this query policy.

Separate public objects, transformations and signed media rather than covering them with one global wildcard. Then configure responsive dimensions and caching as part of the same image-delivery design.

If a Next.js and Supabase media pipeline is producing security, cost or performance problems, book a technical review. We can trace storage policy, URL generation, optimisation and deployment configuration together.

Need help implementing this?

We build high-performance websites and automate workflows for ambitious brands. Let's talk about how we can help your business grow.