Skip to main content
All Docs
FeaturesBlockManOSUpdated March 26, 2026

Image Optimisation: Adopting next/image Across the Platform

Image Optimisation: Adopting next/image Across the Platform

Released in v1.0.88 — 2026-03-26

Overview

Starting with v1.0.88, BlockManOS uses the Next.js Image component (next/image) as the standard for all image rendering. The Avatar component is the first to be migrated as part of the PERF-02 performance initiative. This establishes the technical foundation — remotePatterns configuration, dimension conventions, and the priority API — that all future image work in the platform will build on.

What Changed

Avatar Component

The Avatar component previously rendered user photos using a plain <img> tag. It now uses <NextImage> from next/image.

Before:

<img
  src={src}
  alt={name ?? "Avatar"}
  className={cn("rounded-full object-cover", sizes[size], className)}
/>

After:

<NextImage
  src={src}
  alt={name ?? "Avatar"}
  width={px}
  height={px}
  priority={priority}
  className={cn("rounded-full object-cover", SIZE_CLASS[size], className)}
/>

The component API is unchanged for existing call sites. The only new prop is priority.

Component Props

PropTypeDefaultDescription
srcstring | nullRemote URL or local path for the avatar image.
namestring | nullUsed for the alt attribute and initials fallback.
emailstring | nullUsed for the initials fallback when name is absent.
size"sm" | "md" | "lg""md"Controls rendered dimensions (24 px / 32 px / 48 px).
classNamestringAdditional Tailwind classes applied to the image.
prioritybooleanfalseSet to true for above-the-fold avatars to add a preload hint and skip lazy loading.

Size Reference

size propRendered pxTailwind class
sm24 × 24size-6
md32 × 32size-8
lg48 × 48size-12

Explicit dimensions are required by next/image to reserve intrinsic layout space. This eliminates Cumulative Layout Shift (CLS) caused by images loading into unsized containers.

Using the priority Prop

By default, next/image lazy-loads images — they are only fetched when they enter the viewport. For avatars that appear immediately on page load (e.g. the logged-in user's avatar in the top navigation bar), lazy loading causes an LCP penalty because the browser doesn't know to fetch the image early.

Set priority={true} to override this behaviour:

// Top navigation — logged-in user's own avatar
<Avatar
  src={session.user.image}
  name={session.user.name}
  size="md"
  priority={true}   // ← adds <link rel="preload">, skips lazy loading
/>

// Content list — avatars of other users, below the fold
<Avatar
  src={member.image}
  name={member.name}
  size="sm"
  // priority omitted — defaults to false (lazy loaded)
/>

Only use priority for avatars that are genuinely visible on first paint. Overusing it defeats the purpose of lazy loading.

Remote Patterns Configuration

Next.js requires all external image hostnames to be explicitly allowlisted in next.config.ts before next/image will load from them. The following domains are now configured:

// next.config.ts
images: {
  remotePatterns: [
    { protocol: "https", hostname: "www.gravatar.com", pathname: "/avatar/**" },
    { protocol: "https", hostname: "gravatar.com",     pathname: "/avatar/**" },
    { protocol: "https", hostname: "lh3.googleusercontent.com" },
    { protocol: "https", hostname: "avatars.githubusercontent.com" },
    { protocol: "https", hostname: "*.amazonaws.com" },
    { protocol: "https", hostname: "*.r2.cloudflarestorage.com" },
    { protocol: "https", hostname: "utfs.io" },
  ],
},

If you add a new external image source to the platform, add a corresponding entry to remotePatterns in next.config.ts. Next.js will block any unlisted hostname at build/request time.

Why next/image Matters

BenefitDetail
Format negotiationAutomatically serves WebP or AVIF to browsers that support them, falling back to the source format. No manual conversion needed.
Server-side resizingResizes images to the exact display dimensions on the server. A 2 MB profile photo is never sent to the browser for a 32 px avatar.
CLS eliminationExplicit width/height let the browser reserve space before the image loads, preventing layout shifts.
Lazy loading by defaultOff-screen images are deferred, reducing initial page weight.
LCP optimisationThe priority prop adds a <link rel="preload"> hint for above-the-fold images, improving LCP scores.

Health Endpoint Middleware Bypass

As a small related change in this release, /api/health was added to the authentication middleware bypass list in src/middleware.ts. The health check endpoint now always returns a response without requiring a valid session, making it suitable for use by load balancers, uptime monitors, and deployment health checks.

Bypassed routes (no auth required):

  • /api/inngest
  • /api/webhooks
  • /api/trpc
  • /api/auth
  • /api/health (added in v1.0.88)