{{- $name := site.Params.name | default site.Title -}} {{- $tagline := site.Params.tagline | default "" -}} {{- $description := site.Params.bio | default $tagline | default site.Params.description -}} {{- $avatar := site.Params.avatar -}} {{- /* OG image resolution cascade: 1. params.ogImage = false → emit nothing. 2. params.ogImageUrl set → use it (1200×630 → summary_large_image). 3. params.ogAuto = true AND ogAutoBase + ogAutoFont supplied → auto-generate via Hugo's images.Filter + images.Text overlay at build time. (Bonsai v0.5 ships infra-only; user supplies the base PNG + TTF font.) 4. else fall back to params.avatar (square → summary card). */ -}} {{- $ogImageEnabled := site.Params.ogImage | default true -}} {{- $ogImageUrl := "" -}} {{- $twitterCard := "summary" -}} {{- if $ogImageEnabled -}} {{- if site.Params.ogImageUrl -}} {{- $ogImageUrl = site.Params.ogImageUrl | absURL -}} {{- $twitterCard = "summary_large_image" -}} {{- else if and site.Params.ogAuto site.Params.ogAutoBase site.Params.ogAutoFont -}} {{- $base := resources.Get site.Params.ogAutoBase -}} {{- $font := resources.Get site.Params.ogAutoFont -}} {{- if and $base $font -}} {{- $titleOpts := dict "size" 72 "color" "#2b2b2b" "x" 80 "y" 220 "font" $font -}} {{- $generated := $base | images.Filter (images.Text $name $titleOpts) -}} {{- with $tagline -}} {{- $taglineOpts := dict "size" 36 "color" "#6b6b6b" "x" 80 "y" 340 "font" $font -}} {{- $generated = $generated | images.Filter (images.Text . $taglineOpts) -}} {{- end -}} {{- $ogImageUrl = $generated.Permalink -}} {{- $twitterCard = "summary_large_image" -}} {{- else if $avatar -}} {{- warnf "bonsai: params.ogAuto enabled but ogAutoBase/ogAutoFont resources not found; falling back to avatar" -}} {{- $ogImageUrl = $avatar | absURL -}} {{- end -}} {{- else if $avatar -}} {{- $ogImageUrl = $avatar | absURL -}} {{- end -}} {{- end -}} {{ $name }}{{ with $tagline }} — {{ . }}{{ end }} {{- with $description }} {{- end }} {{- with site.Params.themeColor }} {{- end }} {{- /* hreflang alternates for multi-language sites only. */ -}} {{- if gt (len site.Languages) 1 }} {{- range site.Languages }} {{- end }} {{- end }} {{- if site.Params.manifest }} {{- end }} {{- with $description }} {{- end }} {{- with $ogImageUrl }} {{- end }} {{ partial "schema-person.html" . }} {{ partial "schema-website.html" . }} {{- with site.Params.faviconSvg }} {{- end }} {{- with site.Params.favicon }} {{- end }} {{- with site.Params.appleTouchIcon }} {{- end }} {{- /* Avatar preload: only for `static/`-served paths. When avatar resolves as an `assets/` resource the pipeline emits its own srcset/fetchpriority and a fixed-path preload would be wasted (different filename + format). */ -}} {{- if and site.Params.avatar (ne (site.Params.preloadAvatar | default true) false) (not (strings.HasPrefix site.Params.avatar "http")) (not (resources.Get (strings.TrimPrefix site.Params.avatar "/"))) }} {{- end }} {{- /* Fingerprinted + minified CSS via Hugo's resource pipeline. integrity= attribute lets browsers / CSP `style-src 'self' 'sha384-...'` validate the file. */ -}} {{- $css := resources.Get "css/bonsai.css" | resources.Minify | resources.Fingerprint "sha384" }} {{- if site.Params.rss }} {{- end }} {{- if site.Params.themeToggle }} {{- /* Inline blocking script (no FOUC): apply saved theme before first paint. Tiny (~140B) — meets the <3KB CSS / minimal-JS budget. */ -}} {{- $themeJs := resources.Get "js/theme-toggle.js" | resources.Minify | resources.Fingerprint "sha384" }} {{- end }} {{- if site.Params.share }} {{- $shareJs := resources.Get "js/share.js" | resources.Minify | resources.Fingerprint "sha384" }} {{- end }} {{ partial "analytics-loader.html" . }}