Skip to content

Instantly share code, notes, and snippets.

@moritzsalla
Created July 8, 2026 11:39
Show Gist options
  • Select an option

  • Save moritzsalla/bd75fa1e91da96dbe8c23c6cf06f6abc to your computer and use it in GitHub Desktop.

Select an option

Save moritzsalla/bd75fa1e91da96dbe8c23c6cf06f6abc to your computer and use it in GitHub Desktop.
image-focal-point.ts
import "server-only";
import { cache } from "react";
import type { FocalPoint } from "components/primitives/image/pixel-reveal";
import { getImageUrl, isVectorMimeType } from "lib/amplience/image";
import { computeFocalPoint } from "lib/amplience/image-saliency";
import sharp from "sharp";
// Contrast-saliency focal point for the pixel reveal. Server-side only: one
// tiny thumb per unique asset, cached by the Next data cache, so the client
// never pays a request for this. Enhancement tier: every failure path returns
// null and callers fall back to the per-src default.
const THUMB_WIDTH = 32;
// Never let a decorative input hold a page render: the thumb fetch is a
// third-party CDN call on the server render path (see enrichImageFocalPoints).
const FETCH_TIMEOUT_MS = 1500;
// Cross-request memo. The Next data cache dedupes the thumb fetch, but the
// sharp decode would otherwise rerun on every request; this makes it once
// per process per asset. Refresh-on-hit keeps hot assets resident.
const FOCAL_POINT_CACHE_MAX = 500;
const focalPointCache = new Map<string, FocalPoint | null>();
const cacheFocalPoint = (baseUrl: string, focalPoint: FocalPoint | null) => {
if (focalPointCache.size >= FOCAL_POINT_CACHE_MAX) {
const oldest = focalPointCache.keys().next().value;
if (oldest !== undefined) focalPointCache.delete(oldest);
}
focalPointCache.set(baseUrl, focalPoint);
};
export const getImageFocalPoint = cache(
async (baseUrl: string): Promise<FocalPoint | null> => {
const cached = focalPointCache.get(baseUrl);
if (cached !== undefined) {
focalPointCache.delete(baseUrl);
focalPointCache.set(baseUrl, cached);
return cached;
}
try {
const res = await fetch(`${baseUrl}?w=${THUMB_WIDTH}&qlt=60&fmt=jpg`, {
cache: "force-cache",
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
});
if (!res.ok) return null;
const { data, info } = await sharp(Buffer.from(await res.arrayBuffer()))
.greyscale()
.raw()
.toBuffer({ resolveWithObject: true });
// Cache the analysis result — including a legitimate null (flat image
// with no salient region) so it isn't recomputed. Transient failures
// above fall through uncached and retry on the next request.
const focalPoint = computeFocalPoint(data, info.width, info.height);
cacheFocalPoint(baseUrl, focalPoint);
return focalPoint;
} catch {
return null;
}
},
);
const IMAGE_LINK_SCHEMA =
"http://bigcontent.io/cms/schema/v1/core#/definitions/image-link";
type EnrichableImageLink = {
_meta?: { schema?: typeof IMAGE_LINK_SCHEMA };
defaultHost: string;
endpoint: string;
name: string;
id: string;
mimeType?: string;
focalPoint?: FocalPoint;
};
const isImageLink = (value: object): value is EnrichableImageLink => {
const link = value as Partial<EnrichableImageLink>;
return (
link._meta?.schema === IMAGE_LINK_SCHEMA &&
typeof link.defaultHost === "string" &&
typeof link.endpoint === "string" &&
typeof link.name === "string" &&
typeof link.id === "string"
);
};
/**
* Walks resolved delivery content and attaches a computed contrast focalPoint
* to every raster image link, in place. One awaited pass at the resolver
* choke points (page, PDP content, navigation) gives every CMS surface a
* saliency focalPoint with no adaptor changes. Misses leave links untouched
* and the reveal's per-src fallback applies.
*/
export const enrichImageFocalPoints = async <T>(content: T): Promise<T> => {
const links: EnrichableImageLink[] = [];
const walk = (node: unknown) => {
if (Array.isArray(node)) {
for (const item of node) walk(item);
return;
}
if (typeof node !== "object" || node === null) return;
if (isImageLink(node)) {
links.push(node);
return;
}
for (const value of Object.values(node)) walk(value);
};
walk(content);
await Promise.all(
links
.filter((link) => !isVectorMimeType(link.mimeType))
.map(async (link) => {
const focalPoint = await getImageFocalPoint(getImageUrl(link));
if (focalPoint) link.focalPoint = focalPoint;
}),
);
return content;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment