mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 16:02:26 +00:00
The OG function deployed and worked (`/api/og?v=<nevent>` returns the real title, description, thumbnail and player card), but crawlers hitting `/?v=<nevent>` still got the site-wide card: Vercel evaluates `rewrites` AFTER the filesystem, and `/` matches the static index.html, so the rewrite never fired. Middleware runs before the filesystem check, so that is where the routing belongs. Replace the dead `rewrites` block with a root middleware that matches only `/`, bails immediately when there is no `v` param or the user-agent is not a known preview crawler, and otherwise rewrites to /api/og. Real viewers are unaffected -- they fall through to the untouched SPA. Note the one behavioral difference from the rewrite design: middleware now executes on homepage requests (matcher is `/` only) rather than being invoked solely for crawlers. It returns next() after two cheap checks. Verified on the live unstable deployment that /api/og already renders `x-bitvid-og: video` with og:type video.other for the real note; this only fixes how crawlers reach it. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
44 lines
1.4 KiB
JavaScript
44 lines
1.4 KiB
JavaScript
// Routes crawler requests for `/?v=<nevent>` to the per-video OpenGraph
|
|
// renderer (api/og.js).
|
|
//
|
|
// This has to be middleware rather than a `rewrites` entry in vercel.json:
|
|
// rewrites are evaluated AFTER the filesystem, and `/` matches the static
|
|
// index.html, so the rewrite never fired and crawlers kept getting the
|
|
// site-wide card. Middleware runs before the filesystem check.
|
|
//
|
|
// Deliberately minimal. It matches only `/`, bails immediately when there is no
|
|
// `v` param or the visitor is not a known preview crawler, and never touches
|
|
// the response for a real viewer — they continue to the untouched SPA. If this
|
|
// file is removed the site keeps working, just with the generic card.
|
|
|
|
import { next, rewrite } from "@vercel/edge";
|
|
import { isCrawlerUserAgent } from "./api/_lib/ogRenderer.mjs";
|
|
|
|
export const config = {
|
|
// Only the share-link path. Every other route skips middleware entirely.
|
|
matcher: "/",
|
|
};
|
|
|
|
export default function middleware(request) {
|
|
let url;
|
|
try {
|
|
url = new URL(request.url);
|
|
} catch (err) {
|
|
return next();
|
|
}
|
|
|
|
// A bare homepage visit is not a share link.
|
|
if (!url.searchParams.get("v")) {
|
|
return next();
|
|
}
|
|
|
|
const userAgent = request.headers?.get?.("user-agent") || "";
|
|
if (!isCrawlerUserAgent(userAgent)) {
|
|
return next();
|
|
}
|
|
|
|
const target = new URL(url.toString());
|
|
target.pathname = "/api/og";
|
|
return rewrite(target);
|
|
}
|