diff --git a/website/src/components/ui/OptimisedImage.tsx b/website/src/components/ui/OptimisedImage.tsx
index eda12932e..234c6be45 100644
--- a/website/src/components/ui/OptimisedImage.tsx
+++ b/website/src/components/ui/OptimisedImage.tsx
@@ -1,4 +1,4 @@
-import type { ImgHTMLAttributes } from 'react';
+import type { ImgHTMLAttributes } from "react";
/**
* Wraps an
to serve images through Vercel's edge image optimisation.
@@ -17,7 +17,10 @@ interface StaticImageData {
width: number;
}
-interface OptimisedImageProps extends Omit, 'src'> {
+interface OptimisedImageProps extends Omit<
+ ImgHTMLAttributes,
+ "src"
+> {
/** Desired display width in pixels — used for resizing on the edge. */
width?: number;
/** Image quality 1–100 (default 80). */
@@ -39,36 +42,22 @@ function snapWidth(w: number): number {
return ALLOWED_WIDTHS[ALLOWED_WIDTHS.length - 1];
}
-function optimisedSrc(src: string, width?: number, quality = 80): string {
- // Only optimise local paths served from the same origin
- if (!src.startsWith('/')) {
- return src;
- }
-
- // Skip _next/static paths — already optimized at build time by Next.js
- if (src.startsWith('/_next/')) {
- return src;
- }
-
- // Skip SVGs — vector images can't be raster-optimized
- if (src.endsWith('.svg')) {
- return src;
- }
-
- // Skip in dev — Vercel image API isn't available locally
- if (process.env.NODE_ENV === 'development') {
- return src;
- }
-
- // Vercel's image endpoint requires an explicit width.
- // Fall back to the original asset path when callers omit one.
- if (!width) {
- return src;
- }
+/**
+ * True when the asset should bypass Vercel's image optimiser (external URLs,
+ * already-optimised Next.js static chunks, SVGs, local dev, or missing width).
+ */
+function shouldSkipOptimisation(src: string, width?: number): boolean {
+ if (!src.startsWith("/")) return true;
+ if (src.startsWith("/_next/")) return true;
+ if (src.endsWith(".svg")) return true;
+ if (process.env.NODE_ENV === "development") return true;
+ if (!width) return true;
+ return false;
+}
- const dpr = 1;
+function optimisedSrc(src: string, width: number, quality = 80): string {
const params = new URLSearchParams({ url: src, q: String(quality) });
- params.set('w', String(snapWidth(Math.round(width * dpr))));
+ params.set("w", String(snapWidth(Math.round(width))));
return `/_vercel/image?${params}`;
}
@@ -76,12 +65,42 @@ export default function OptimisedImage({
src,
width,
quality = 80,
- alt = '',
+ alt = "",
...rest
}: OptimisedImageProps) {
// Resolve Next.js static imports (StaticImageData) to their .src string
- const rawSrc = typeof src === 'object' && src !== null && 'src' in src ? src.src : src;
- const resolvedSrc = typeof rawSrc === 'string' ? optimisedSrc(rawSrc, width, quality) : undefined;
+ const rawSrc =
+ typeof src === "object" && src !== null && "src" in src ? src.src : src;
+
+ if (typeof rawSrc !== "string") {
+ return (
+
+ );
+ }
+
+ if (shouldSkipOptimisation(rawSrc, width)) {
+ return (
+
+ );
+ }
+
+ // width is guaranteed by shouldSkipOptimisation above
+ const w = width!;
+ const src1x = optimisedSrc(rawSrc, w, quality);
+ const src2x = optimisedSrc(rawSrc, w * 2, quality);
+
+ // If 1x and 2x snap to the same allowed width, the browser would download
+ // the same file twice via srcset — skip the descriptor in that case.
+ const srcSet = src1x === src2x ? undefined : `${src1x} 1x, ${src2x} 2x`;
- return
;
+ return (
+
+ );
}