SEO & i18n


Structured data, Open Graph, Twitter cards, and multilingual support

Beautiful Hugo includes comprehensive SEO support (schema.org, Open Graph, Twitter Cards) and full multilingual capabilities via Hugo’s i18n system.

Schema.org Structured Data

The theme automatically generates JSON-LD structured data for every page:

TypeWhere UsedWhat It Contains
WebSiteAll pagesSite name, URL, search action
OrganizationAll pagesOrganization name, logo, URL
WebPageAll pagesPage name, description, breadcrumb
ArticleBlog postsHeadline, author, datePublished, dateModified, publisher, wordCount, timeRequired
BreadcrumbListAll pagesNavigation hierarchy

No configuration is required — the structured data is generated from your existing hugo.toml settings and page front matter. You can optionally customize the structured data output with the following params:

Custom Structured Data Params

ParamSchema TypeDescription
organizationNameOrganizationOrganization name (defaults to Params.author.name)
organizationLogoOrganizationURL of the organization logo
organizationAddressOrganizationOrganization address (string or structured value)
socialProfilesOrganizationList of social profile URLs for the sameAs field
alternatePageNameWebSiteAlternate name for the site (used as alternateName)
[Params]
  organizationName = "My Company"
  organizationLogo = "https://example.com/logo.png"
  socialProfiles = ["https://twitter.com/example", "https://github.com/example"]
  alternatePageName = "My Company Blog"

Open Graph

Open Graph meta tags are generated automatically via Hugo’s built-in internal template:

<meta property="og:title" content="..." />
<meta property="og:description" content="..." />
<meta property="og:type" content="article" />
<meta property="og:image" content="..." />

The image is resolved from a cascade: share_imgimagelogo.

Twitter Cards

Twitter Card meta tags use the summary_large_image card type:

<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content="@username" />
<meta name="twitter:creator" content="@username" />

The @site and @creator values come from Params.author.twitter.

Robots Meta Tags

Beautiful Hugo can generate <meta name="robots"> tags from three configuration layers:

  1. hugo.toml — site-wide defaults (only applied to pages in mainSections)
  2. _index.md — section-level overrides
  3. Page front matter — per-page overrides (highest priority)

Each layer overrides matching keys from the previous one.

Boolean Tags

The following tags are supported (set to true to include them):

TagEffect
noindexDo not index this page
nofollowDo not follow links on this page
noneEquivalent to noindex, nofollow
nosnippetDo not show a text snippet or video preview
notranslateDo not offer translation of this page in search results
noimageindexDo not index images on this page
noarchiveDo not show a cached link in search results
nocacheSimilar to noarchive (Bing-specific)
noaiDo not use content for AI training (per dev.ai proposal)
noimageaiDo not use images for AI training

AI Summary Limits

The ai-summary-limit key controls how much of your page content search engines may use for AI-generated summaries:

ValueEffect
noneNo limit (no meta tag emitted)
nosnippetBlock all snippets / AI summaries
0Same as nosnippet
50, 150, 300Character limit for snippets

Site-Wide Configuration

[Params.seo.robots]
  ai-summary-limit = "nosnippet"
  noindex = true
  nofollow = true

[Params.seo.GoogleBot]
  noindex = true
  ai-summary-limit = 50

This produces:

<meta name="robots" content="nosnippet, noindex, nofollow">
<meta name="googlebot" content="noindex, max-snippet:50">

You can add entries for other bots (e.g. Bingbot, DuckDuckBot) the same way.

Per-Page Overrides

Override or supplement site-wide settings in any page’s front matter:

seo:
  robots:
    ai-summary-limit: none
  GoogleBot:
    noindex: false

ExpiryDate

Set ExpiryDate in front matter to add an unavailable_after directive:

---
title: Event Post
expiryDate: 2026-12-31
---

This generates:

<meta name="robots" content="unavailable_after: 2026-12-31T00:00:00+00:00" />

Description Cascade

The page description (used in meta tags and structured data) follows this cascade:

  1. .Description (explicit front matter description field)
  2. .Params.subtitle (the subtitle)
  3. .Summary (auto-generated from content)

Multilingual Support

Beautiful Hugo supports Hugo’s standard multilingual configuration with per-language content directories.

Configuration

DefaultContentLanguage = "en"

[languages]
  [languages.en]
    title = "My Site"
    weight = 1
    contentDir = "content/en"

  [languages.fr]
    title = "Mon Site"
    weight = 2
    contentDir = "content/fr"

Language Switcher

A language switcher appears in the navbar:

  • 2 languages: Inline links next to each other
  • 3+ languages: Dropdown menu

Supported Languages

Beautiful Hugo ships with translations for 20 languages:

CodeLanguage
enEnglish
deGerman
dkDanish
eoEsperanto
esSpanish
frFrench
hrCroatian
itItalian
jaJapanese
koKorean
lmoLombard
nbNorwegian Bokmål
nlDutch
plPolish
ptPortuguese
pt-brPortuguese (Brazil)
ruRussian
trTurkish
zh-CNChinese (Simplified)
zh-TWChinese (Traditional)

Translation Keys

The i18n files provide translations for common UI strings:

KeyPurpose
postedOnDate“Posted on January 2, 2006”
lastModified“Last modified on …”
readMore“Read more” link text
readingTime“3 min read”
olderPosts / newerPostsPagination labels
previousPost / nextPostPost navigation
pageNotFound404 page text
themeToggleLabelTheme toggle accessibility label
comments“Comments” heading
seeAlso“See also” related posts heading

To add a new language, create a new file in i18n/ (e.g. i18n/pt.yaml for Portuguese) with translations for these keys.

Navbar menu items are automatically translated when the menu entry has an identifier that matches an i18n key with the menu_ prefix. If no matching translation key exists, the menu name from hugo.toml is used as a fallback.

For example, given this menu config:

[[menu.main]]
    identifier = "blog"
    name = "Blog"
    weight = 1

[[menu.main]]
    parent = "blog"
    name = "Posts"
    identifier = "post"
    url = "post/"
    weight = 1

The theme looks up menu_blog and menu_post in the current language’s i18n file. In French (i18n/fr.yaml):

- id: menu_blog
  translation: "Blog"
- id: menu_post
  translation: "Articles"

The theme ships with pre-built translations for common menu items (blog, posts, tags, categories, archives, about, and the example-site section names). You can add your own menu_* keys to your site’s i18n overrides to translate custom menu items.

RSS

When rss = true, an RSS icon appears in the footer and alternate feed links are included in <head>:

[Params]
  rss = true

Hugo auto-generates RSS feeds at /index.xml (site-wide) and /post/index.xml (section-specific).

Google Analytics

Set the tracking ID in your config (loaded only in production):

[Services]
  [Services.googleAnalytics]
    id = "G-XXXXXXXXXX"

Piwik / Matomo

[Params]
  [Params.piwik]
    server = "analytics.example.com"
    id = 1
ParamTypeDescription
piwik.serverstringPiwik/Matomo server hostname
piwik.idstringPiwik/Matomo site ID

Google Custom Search Engine

When gcse is set, a search icon appears in the navbar that opens a search modal:

[Params]
  gcse = "012345678901234567890:abcdefghijk"

The integrated client-side search requires JSON output to function. Ensure your hugo.toml includes the following outputs configuration:

[outputs]
  home = ["HTML", "RSS", "JSON"]
  section = ["HTML", "RSS", "JSON"]
  page = ["HTML"]

Enable the built-in search UI by configuring a provider:

ParamTypeDefaultDescription
[Params.search] providerstring"fuse"Search provider to use. Set to "none" to disable the built-in search UI.
[Params.search]
  provider = "fuse"

Search labels come from the theme’s i18n files. To localize or customize labels, override the relevant translation keys in your site, such as searchPlaceholder, searchResultsLabel, searchNoResultsText, searchPrevText, and searchNextText.