Integration
Safe link previews in the Next.js App Router.
Keep arbitrary outbound fetches in a Route Handler, validate caller input, and make failures local to the preview card.
Create the route handler
npm install linkpeek
// app/api/preview/route.ts
import { preview } from "linkpeek";
import { type NextRequest, NextResponse } from "next/server";
export async function GET(request: NextRequest) {
const url = request.nextUrl.searchParams.get("url");
if (!url) {
return NextResponse.json({ error: "Missing url" }, { status: 400 });
}
try {
const result = await preview(url);
return NextResponse.json(result, {
headers: {
"Cache-Control":
result.statusCode < 400 ? "public, s-maxage=3600" : "no-store",
},
});
} catch {
return NextResponse.json({ error: "Preview unavailable" }, { status: 422 });
}
}
Cache successes, not broken targets
The response cache prevents repeated network fetches from dominating render latency. Cache only successful previews, choose a TTL that fits your product, and consider request coalescing when many users share the same URL at once.
Do not forward cookies, authorization headers, internal tokens, or caller-provided credentials to the target URL.
Render metadata as untrusted data
React escapes text by default. Keep it that way. Allow images only from origins covered by your image policy, treat canonical and media URLs as untrusted links, and provide a hostname-only fallback card when extraction fails.