diff --git a/.github/workflows/smoke.sh b/.github/workflows/smoke.sh
index 66073cd..7ff4c02 100644
--- a/.github/workflows/smoke.sh
+++ b/.github/workflows/smoke.sh
@@ -132,6 +132,169 @@ echo "ok: md navbar theme toggle"
curl -sf -X DELETE "$BASE/api/artifacts/ci-md" -H "$AUTH" > /dev/null
+# --- link previews: description + og:image in the heads the server renders ---
+# Two pages carry them, both built per request: the viewer frame (every type) and the md render.
+# A raw html view carries nothing, because those bytes are the author's document.
+curl -s -X DELETE "$BASE/api/artifacts/ci-preview" -H "$AUTH" > /dev/null
+curl -s -X DELETE "$BASE/api/artifacts/ci-preview-md" -H "$AUTH" > /dev/null
+
+code=$(curl -s -o /dev/null -w '%{http_code}' -X POST "$BASE/api/artifacts" -H "$AUTH" -H "$JSON" \
+ -d '{"content":"
preview
","type":"html","slug":"ci-preview","visibility":"public","description":"what this page is","ogImage":"https://example.com/preview.png"}')
+expect_code 201 "$code" "publish with a description and an image"
+
+framed=$(curl -s "$BASE/a/ci-preview")
+printf '%s' "$framed" | grep -qF '' \
+ || fail "framed view is missing the plain description tag"
+printf '%s' "$framed" | grep -qF '' \
+ || fail "framed view is missing og:description"
+printf '%s' "$framed" | grep -qF '' \
+ || fail "framed view is missing og:image"
+printf '%s' "$framed" | grep -qF '' \
+ || fail "framed view is missing og:title"
+# The canonical link, never the capability link: an unfurl outlives the paste it came from.
+printf '%s' "$framed" | grep -qF "" \
+ || fail "framed view og:url is not the canonical link"
+printf '%s' "$framed" | grep -qF 'content="summary_large_image"' \
+ || fail "an artifact with an image did not ask for the large card"
+echo "ok: framed view carries the link preview"
+
+# The author's own bytes stay the author's own bytes.
+raw=$(curl -s "$BASE/a/ci-preview?raw=1")
+if printf '%s' "$raw" | grep -q 'og:'; then fail "raw html view had preview tags spliced into it"; fi
+printf '%s' "$raw" | grep -qF 'preview
' || fail "raw html view lost its body"
+echo "ok: a raw html view is left alone"
+
+# md renders its own head, so it carries the tags with the frame off, where no frame runs.
+curl -sf -X POST "$BASE/api/artifacts" -H "$AUTH" -H "$JSON" \
+ -d '{"content":"# preview md","type":"md","slug":"ci-preview-md","visibility":"public","description":"a markdown page","frame":false}' > /dev/null \
+ || fail "could not publish the md artifact the preview check reads"
+mdpreview=$(curl -s "$BASE/a/ci-preview-md")
+if printf '%s' "$mdpreview" | grep -q '