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 #}