Hugo SEO on a Multi-Section Blog
Search and social previews on a Hugo blog are mostly template work: consistent titles, a real summary, a thumbnail, Open Graph / Twitter tags, structured data, and a sitemap. DevOpsTales does that in layouts/_default/baseof.html plus a JSON-LD partial—no SEO plugin required.

Front matter and summaries
This site does not use a description field in post front matter. Listing pages, RSS, and social cards pull the teaser from the body: write one or two short paragraphs, then <!--more-->. Hugo’s .Summary becomes the plain-text blurb.
Always set:
title: "Clear, specific title"
thumbnail: "img/your-image.webp"
thumbnail should live under static/ (referenced without the static/ prefix). Prefer WebP. If a post omits it, baseof falls back to a site default image.
Optional keywords feed JSON-LD; they are not a substitute for a good summary.
Open Graph and Twitter cards
config.toml enables the usual flags:
[Params]
opengraph = true
twitter_cards = true
The site shell also sets explicit tags in layouts/_default/baseof.html: og:title, og:description, og:url, og:image, twitter:card (summary_large_image), and related fields. Description prefers .Description when present, otherwise .Summary | plainify. Image URLs are absolutized from the thumbnail.
That gives Slack, Mastodon, X, and similar scrapers a stable preview without relying only on Hugo’s internal templates.
JSON-LD
layouts/partials/seo_schema.html emits application/ld+json:
- Home:
WebSitewith name, URL, site description - Posts:
BlogPostingwith headline, dates, author, section, word count, reading time, keywords, and image
Include it once from baseof in <head>. Keep author name and logo paths aligned with [Params.author] / site params so the graph stays consistent.
Sitemap, robots, and canonical URLs
enableRobotsTXT = true
canonifyURLs = true
[sitemap]
changefreq = "daily"
filename = "sitemap.xml"
priority = 0.5
canonifyURLs rewrites links against baseurl (https://devopstales.github.io/), which avoids mixed relative/absolute surprises in feeds and meta tags. Custom layouts/sitemap.xml and layouts/robots.txt let you tune crawler hints if the defaults are not enough.
WebManifest
Home outputs include WebManifest, with a small layouts/index.webmanifest template. It is a light installability / branding signal, not a full PWA, but it belongs in the same “how does the browser see this site” bucket as SEO metadata.
Checklist for a new post
- Specific
title thumbnailpointing at an existing WebP understatic/img/- Teaser paragraphs +
<!--more-->(nodescription:key) - Sensible
tags/categories/ optionalkeywords - After deploy, share the URL in a private Slack/Discord channel or use a debugger to confirm OG tags
- Spot-check
/sitemap.xmlcontains the new permalink
curl -s https://devopstales.github.io/hugo/hugo-seo/ | grep -E 'og:title|og:image|twitter:card'
curl -s https://devopstales.github.io/sitemap.xml | grep hugo-seo
Summary
SEO here is disciplined content fields plus head templates: summary from <!--more-->, thumbnails for images, OG/Twitter tags in baseof, BlogPosting JSON-LD, sitemap/robots, and optional WebManifest. Get those right and most “SEO plugins” become unnecessary for a technical blog.