diff --git a/layouts/_partials/bibliography-json-ld.html b/layouts/_partials/bibliography-json-ld.html
new file mode 100644
index 00000000..b83b770f
--- /dev/null
+++ b/layouts/_partials/bibliography-json-ld.html
@@ -0,0 +1,287 @@
+{{- /*
+ bibliography-json-ld.html
+ Emits a
+
+{{- else if .IsSection -}}
+
+{{- /* ── COLLECTION PAGE (bibliography index) ──────────────────────────── */ -}}
+{{- $pages := .RegularPages -}}
+{{- $pages = sort $pages "Date" "desc" -}}
+{{- $pages = sort $pages "Title" "asc" -}}
+
+{{- $itemList := slice -}}
+{{- range $i, $p := $pages -}}
+ {{- $itemList = append (dict
+ "@type" "ListItem"
+ "position" (add $i 1)
+ "name" $p.Title
+ "url" $p.Permalink
+ ) $itemList -}}
+{{- end -}}
+
+{{- $desc := .Description | default "A bibliography of publications, patents, reports, and other artifacts related to the Interlisp programming environment." -}}
+
+{{- $ld := dict
+ "@context" "https://schema.org"
+ "@type" "CollectionPage"
+ "name" .Title
+ "url" .Permalink
+ "description" $desc
+ "inLanguage" "en-US"
+ "mainEntity" (dict
+ "@type" "ItemList"
+ "name" .Title
+ "numberOfItems" (len $pages)
+ "itemListElement" $itemList
+ )
+-}}
+
+
+
+{{- end -}}
+
+{{- end -}}
diff --git a/layouts/_partials/hooks/head-end.html b/layouts/_partials/hooks/head-end.html
index 9daa28c0..f800ce9f 100644
--- a/layouts/_partials/hooks/head-end.html
+++ b/layouts/_partials/hooks/head-end.html
@@ -1,2 +1,3 @@
+{{ partial "bibliography-json-ld.html" . }}
diff --git a/scripts/bibSplit.pl b/scripts/bibSplit.pl
index 8a9b77be..97356543 100755
--- a/scripts/bibSplit.pl
+++ b/scripts/bibSplit.pl
@@ -58,10 +58,12 @@ sub sanitize_text {
my $type = $obj->{type} // '';
- # Titles can have colons and other special characters. Place YAML keyword on one line
- # and follow it with the title indented on subsequent line
+ # Titles can have colons and other special characters. Use a YAML double-quoted scalar
+ # so the decoded value has no trailing newline (the literal-block `|` style would add one).
my $itemTitle = sanitize_text($obj->{title} // '');
- my $title = $itemTitle eq '' ? "title: ''" : "title: |\n $itemTitle\n";
+ (my $escapedTitle = $itemTitle) =~ s/\\/\\\\/g;
+ $escapedTitle =~ s/"/\\"/g;
+ my $title = $itemTitle eq '' ? "title: ''" : "title: \"$escapedTitle\"";
# Abstracts can be multi-line and contain multiple paragraphs. Place YAML keyword on
# one line and follow it with the abstract indented on subsequent lines.