diff --git a/config/_default/params.yaml b/config/_default/params.yaml
index 32624461..f34c98c7 100644
--- a/config/_default/params.yaml
+++ b/config/_default/params.yaml
@@ -2,7 +2,8 @@ favicon: /favicon.png
# Pas de / pour les ressources qui seront transformées
# Et les placer dans /assets et non dans /static
logo: logo-large.png
-description: "et ses opinions impopulaires"
+description: "Richard Dern et ses opinions impopulaires"
+themeColor: "#060c14"
search:
action: /recherche/
param: q
diff --git a/layouts/partials/head/description.html b/layouts/partials/head/description.html
new file mode 100644
index 00000000..dbb0ec01
--- /dev/null
+++ b/layouts/partials/head/description.html
@@ -0,0 +1,18 @@
+{{- $description := .Description | default "" -}}
+{{- if not $description -}}
+ {{- $description = .Summary | plainify | htmlUnescape -}}
+{{- end -}}
+{{- if not $description -}}
+ {{- $description = .Plain | htmlUnescape -}}
+{{- end -}}
+{{- if not $description -}}
+ {{- $description = .Content | plainify | htmlUnescape -}}
+{{- end -}}
+{{- if not $description -}}
+ {{- $description = site.Params.description | default "" -}}
+{{- end -}}
+{{- $description = $description | replaceRE "\\s+" " " | strings.TrimSpace -}}
+{{- if gt (len $description) 180 -}}
+ {{- $description = truncate 180 $description -}}
+{{- end -}}
+{{- return $description -}}
diff --git a/layouts/partials/head/metadata.html b/layouts/partials/head/metadata.html
new file mode 100644
index 00000000..1c80269a
--- /dev/null
+++ b/layouts/partials/head/metadata.html
@@ -0,0 +1,68 @@
+{{- $title := site.Title -}}
+{{- if not .IsHome -}}
+ {{- $title = printf "%s | %s" .Title site.Title -}}
+{{- end -}}
+{{- $socialTitle := site.Title -}}
+{{- if not .IsHome -}}
+ {{- $socialTitle = .Title -}}
+{{- end -}}
+{{- $description := partial "head/description.html" . -}}
+{{- $socialImage := partial "head/social-image.html" . -}}
+{{- $searchPath := site.Params.search.action | relURL -}}
+{{- $isSearchPage := eq .RelPermalink $searchPath -}}
+{{- $robots := "max-image-preview:large" -}}
+{{- if $isSearchPage -}}
+ {{- $robots = "noindex, follow" -}}
+{{- end -}}
+{{- $ogType := "website" -}}
+{{- if and .IsPage (not $isSearchPage) -}}
+ {{- $ogType = "article" -}}
+{{- end -}}
+{{- $localeCode := site.LanguageCode | default site.Language.LanguageCode | default "fr-FR" -}}
+{{- $locale := replace $localeCode "-" "_" -}}
+
{{ $title }}
+{{- with $description }}
+
+{{- end }}
+
+
+
+
+
+
+
+
+{{- with $description }}
+
+{{- end }}
+{{- with $socialImage.url }}
+
+{{- end }}
+{{- with $socialImage.width }}
+
+{{- end }}
+{{- with $socialImage.height }}
+
+{{- end }}
+{{- with $socialImage.alt }}
+
+{{- end }}
+
+
+{{- with $description }}
+
+{{- end }}
+{{- with $socialImage.url }}
+
+{{- end }}
+{{- with $socialImage.alt }}
+
+{{- end }}
+{{- if eq $ogType "article" -}}
+ {{- with .Date }}
+
+ {{- end }}
+ {{- with .Lastmod }}
+
+ {{- end }}
+{{- end -}}
diff --git a/layouts/partials/head/social-image.html b/layouts/partials/head/social-image.html
new file mode 100644
index 00000000..3199b944
--- /dev/null
+++ b/layouts/partials/head/social-image.html
@@ -0,0 +1,55 @@
+{{- $image := false -}}
+{{- $isCoverImage := false -}}
+{{- $alt := "" -}}
+{{- with .Params.cover -}}
+ {{- $cover := $.Resources.GetMatch . -}}
+ {{- if and $cover (ne $cover.MediaType.SubType "svg") -}}
+ {{- $image = $cover -}}
+ {{- $isCoverImage = true -}}
+ {{- $coverName := path.Base . | replaceRE "\\.[^.]+$" "" -}}
+ {{- $coverDataFile := $.Resources.Get (printf "data/images/%s.yaml" $coverName) -}}
+ {{- if not $coverDataFile -}}
+ {{- $coverDataFile = $.Resources.Get (printf "data/%s.yaml" $coverName) -}}
+ {{- end -}}
+ {{- $coverData := dict -}}
+ {{- if $coverDataFile -}}
+ {{- $coverData = $coverDataFile.Content | transform.Unmarshal -}}
+ {{- end -}}
+ {{- $alt = index $coverData "description" | default "" -}}
+ {{- if not $alt -}}
+ {{- $alt = index $coverData "title" | default "" -}}
+ {{- end -}}
+ {{- end -}}
+{{- end -}}
+{{- if not $image -}}
+ {{- $logoPath := site.Params.logo | default "logo-large.png" -}}
+ {{- $logo := resources.GetMatch $logoPath -}}
+ {{- if and $logo (ne $logo.MediaType.SubType "svg") -}}
+ {{- $image = $logo -}}
+ {{- end -}}
+{{- end -}}
+{{- if not $alt -}}
+ {{- if and $image $isCoverImage -}}
+ {{- if and .IsPage (not .IsHome) -}}
+ {{- $alt = printf "Image de partage pour %s" .Title -}}
+ {{- else -}}
+ {{- $alt = printf "Logo du site %s" site.Title -}}
+ {{- end -}}
+ {{- else if $image -}}
+ {{- $alt = printf "Logo du site %s" site.Title -}}
+ {{- end -}}
+{{- end -}}
+{{- $data := dict -}}
+{{- if $image -}}
+ {{- $data = dict
+ "url" $image.Permalink
+ "alt" ($alt | strings.TrimSpace | truncate 420)
+ -}}
+ {{- with $image.Width -}}
+ {{- $data = merge $data (dict "width" .) -}}
+ {{- end -}}
+ {{- with $image.Height -}}
+ {{- $data = merge $data (dict "height" .) -}}
+ {{- end -}}
+{{- end -}}
+{{- return $data -}}
diff --git a/themes/2026/layouts/_partials/head.html b/themes/2026/layouts/_partials/head.html
index ea2d474e..8de31d0d 100644
--- a/themes/2026/layouts/_partials/head.html
+++ b/themes/2026/layouts/_partials/head.html
@@ -1,13 +1,6 @@
-{{ if .IsHome }}{{ site.Title }}{{ else }}{{ printf "%s | %s" .Title site.Title }}{{ end }}
-{{ with .Description }}
-
-{{ else }}
-{{ with site.Params.description }}
-
-{{ end }}
-{{ end }}
+{{ partial "head/metadata.html" . }}
diff --git a/themes/42/layouts/_partials/head.html b/themes/42/layouts/_partials/head.html
index 5b9cef15..c535163b 100644
--- a/themes/42/layouts/_partials/head.html
+++ b/themes/42/layouts/_partials/head.html
@@ -1,6 +1,6 @@
-{{ if .IsHome }}{{ site.Title }}{{ else }}{{ printf "%s | %s" .Title site.Title }}{{ end }}
+{{ partial "head/metadata.html" . }}