From 2ebe63ffff4a9638e2324cb4bad38168a8d670d6 Mon Sep 17 00:00:00 2001 From: Ricardo Date: Wed, 18 Feb 2026 17:17:30 +0100 Subject: [PATCH] fix: use eleventyComputed for OG slug to avoid Nunjucks race condition Eleventy 3.x renders Nunjucks templates in parallel, causing page.url to return wrong values in {% set %} tags. This caused OG images to be mismatched between pages (e.g., bookmark showed note's OG image). Move ogSlug and hasOgImage computation to eleventyComputed, which runs during the sequential data cascade phase before parallel rendering. The computed values are then available as plain template variables. Refs: https://github.com/11ty/eleventy/issues/3183 --- _data/eleventyComputed.js | 33 +++++++++++++++++++++++++++++++++ _includes/layouts/base.njk | 13 ++++++------- 2 files changed, 39 insertions(+), 7 deletions(-) create mode 100644 _data/eleventyComputed.js diff --git a/_data/eleventyComputed.js b/_data/eleventyComputed.js new file mode 100644 index 0000000..2b58219 --- /dev/null +++ b/_data/eleventyComputed.js @@ -0,0 +1,33 @@ +/** + * Computed data resolved during the data cascade (sequential, per-page). + * + * Eleventy 3.x renders Nunjucks templates in parallel, which causes + * `page.url` and `page.fileSlug` to return wrong values when read + * via {% set %} in templates. By computing OG-related values here, + * they are resolved before parallel rendering begins. + * + * See: https://github.com/11ty/eleventy/issues/3183 + */ + +import { existsSync } from "node:fs"; +import { resolve, dirname } from "node:path"; +import { fileURLToPath } from "node:url"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); + +export default { + ogSlug: (data) => { + const url = data.page?.url; + if (!url) return ""; + return url.replace(/\/$/, "").split("/").pop(); + }, + + hasOgImage: (data) => { + const url = data.page?.url; + if (!url) return false; + const slug = url.replace(/\/$/, "").split("/").pop(); + if (!slug) return false; + const ogPath = resolve(__dirname, "..", ".cache", "og", `${slug}.png`); + return existsSync(ogPath); + }, +}; diff --git a/_includes/layouts/base.njk b/_includes/layouts/base.njk index e6d009c..a20af0c 100644 --- a/_includes/layouts/base.njk +++ b/_includes/layouts/base.njk @@ -23,16 +23,15 @@ - {% set ogFileSlug = page.url | ogSlug %} - {% set hasGeneratedOg = ogFileSlug | hasOgImage %} + {# ogSlug and hasOgImage are pre-computed via eleventyComputed (race-condition safe) #} {% if ogPhoto and ogPhoto != "" and (ogPhoto | length) > 10 %} {% elif image and image != "" and (image | length) > 10 %} {% elif contentImage and contentImage != "" and (contentImage | length) > 10 %} - {% elif hasGeneratedOg %} - + {% elif hasOgImage %} + {% else %} {% endif %} @@ -41,7 +40,7 @@ {# Twitter Card meta tags #} - {% set hasImage = hasGeneratedOg or (ogPhoto and ogPhoto != "" and (ogPhoto | length) > 10) or (image and image != "" and (image | length) > 10) or (contentImage and contentImage != "" and (contentImage | length) > 10) %} + {% set hasImage = hasOgImage or (ogPhoto and ogPhoto != "" and (ogPhoto | length) > 10) or (image and image != "" and (image | length) > 10) or (contentImage and contentImage != "" and (contentImage | length) > 10) %} @@ -51,8 +50,8 @@ {% elif contentImage and contentImage != "" and (contentImage | length) > 10 %} - {% elif hasGeneratedOg %} - + {% elif hasOgImage %} + {% endif %} {# Favicon #}