Index: src/views/shell.ejs
===================================================================
--- src/views/shell.ejs	(revision 5eef817483804be6a13b52f068413569df6810b0)
+++ src/views/shell.ejs	(revision 69815b232bc91b7504ea8b28d3e2f66949f216ed)
@@ -57,7 +57,14 @@
   ? socialDescr
   : (safeSite.default_description || safeSite.description || '');
-const _socialImage = (typeof socialImage !== 'undefined' && socialImage)
-  ? socialImage
-  : (safeSite.og_image_default || safeSite.default_cover || '');
+// og:image — custom (post/site) first; otherwise the auto-generated themed card
+// (/og/<slug>.png), so every site has a branded social preview by default.
+let _socialImage = '', _ogGenerated = false;
+if (typeof socialImage !== 'undefined' && socialImage) _socialImage = socialImage;
+else if (safeSite.og_image_default) _socialImage = safeSite.og_image_default;
+else if (safeSite.default_cover) _socialImage = safeSite.default_cover;
+else if (safeSite.slug && typeof ogOrigin !== 'undefined' && ogOrigin) {
+  _socialImage = ogOrigin + '/og/' + encodeURIComponent(safeSite.slug) + '.png';
+  _ogGenerated = true;
+}
 const _ogType = isPostPage ? 'article' : 'website';
 
@@ -139,4 +146,9 @@
 <meta property="og:image"     content="<%= _e(_socialImage) %>">
 <meta property="og:image:alt" content="<%= _e(_socialTitle) %>">
+<% if (_ogGenerated) { %>
+<meta property="og:image:width"  content="1200">
+<meta property="og:image:height" content="630">
+<meta property="og:image:type"   content="image/png">
+<% } %>
 <% } %>
 <% if (_canonical) { %><meta property="og:url" content="<%= _e(_canonical) %>"><% } %>
