/** * Patch @rmdes/indiekit-syndicator-bluesky so that own-domain post URLs * don't fetch OG metadata via the internal URL. * * Problem: fetchOpenGraphData() rewrites own-blog URLs to the Node.js * internal address (INTERNAL_FETCH_URL). But static Eleventy pages are * served by nginx on the web jail — not by the Node.js process. The * internal fetch therefore hits Indiekit's CMS which responds with an * authentication page whose og:title is "Indiekit Authenticate", so * Bluesky cards end up titled "Indiekit Authenticate". * * Fix: * 1. createExternalEmbed() accepts optional `title`/`description` in * options and skips fetchOpenGraphData() when they are provided for * own-domain URLs. * 2. post() passes title/description derived from JF2 properties when * the embed URL is an own-domain post permalink. */ import { access, readFile, writeFile } from "node:fs/promises"; const MARKER = "// [patch] bluesky-og-own-post-title"; const TARGET = "node_modules/@rmdes/indiekit-syndicator-bluesky/lib/bluesky.js"; // ── Replacement 1: createExternalEmbed — skip fetchOpenGraphData for own posts const OLD_OG_FETCH = ` // Fetch OG metadata from HTML (needed for title/description, // and as image fallback for external URLs) const ogData = await fetchOpenGraphData(url);`; const NEW_OG_FETCH = ` // Fetch OG metadata from HTML (needed for title/description, // and as image fallback for external URLs). // For own-domain posts skip the HTML fetch: _toInternalUrl() rewrites // to the Node.js jail which serves Indiekit admin (auth page), not the // static Eleventy output. Use caller-supplied title/description instead. ${MARKER} const ogData = isOwnPost && (options.title || options.description) ? { title: options.title || url, description: options.description || "", imageUrl: null, } : await fetchOpenGraphData(url);`; // ── Replacement 2: post() — pass title/description for own-domain embed URLs const OLD_EMBED_CALL = ` // Create OG embed: // - External URL exists → use it as OG card (permalink is in text) // - No external URL → use permalink as OG card let externalEmbed = null; if (!images?.length) { const embedUrl = externalUrl || properties.url; if (embedUrl) { externalEmbed = await this.createExternalEmbed(embedUrl, { me }); } }`; const NEW_EMBED_CALL = ` // Create OG embed: // - External URL exists → use it as OG card (permalink is in text) // - No external URL → use permalink as OG card let externalEmbed = null; if (!images?.length) { const embedUrl = externalUrl || properties.url; if (embedUrl) { // For own-domain post URLs the internal fetch would hit the Indiekit // auth page instead of the static HTML. Supply title/description from // JF2 properties so fetchOpenGraphData() is bypassed. ${MARKER} const _meNorm = me?.replace(/\\/+$/, ""); const _isOwnEmbed = _meNorm && embedUrl.startsWith(_meNorm); let _embedOpts = { me }; if (_isOwnEmbed) { const _rawText = properties.content?.text || (properties.content?.html ? properties.content.html .replace(/<[^>]+>/g, " ") .replace(/\\s+/g, " ") .trim() : ""); _embedOpts.title = (properties.name || _rawText.slice(0, 100).trim() || embedUrl); _embedOpts.description = _rawText.slice(0, 300).trim(); } externalEmbed = await this.createExternalEmbed(embedUrl, _embedOpts); } }`; async function exists(p) { try { await access(p); return true; } catch { return false; } } if (!(await exists(TARGET))) { console.log(`[postinstall] bluesky-og-own-post-title: ${TARGET} not found — skipping`); process.exit(0); } const source = await readFile(TARGET, "utf8"); if (source.includes(MARKER)) { console.log("[postinstall] bluesky-og-own-post-title: already applied"); process.exit(0); } const missing = []; if (!source.includes(OLD_OG_FETCH)) missing.push("OG fetch snippet"); if (!source.includes(OLD_EMBED_CALL)) missing.push("embed call snippet"); if (missing.length) { console.warn( `[postinstall] bluesky-og-own-post-title: snippets not found — skipping (${missing.join(", ")})`, ); process.exit(0); } const updated = source .replace(OLD_OG_FETCH, NEW_OG_FETCH) .replace(OLD_EMBED_CALL, NEW_EMBED_CALL); await writeFile(TARGET, updated, "utf8"); console.log(`[postinstall] Patched bluesky-og-own-post-title in ${TARGET}`);