Table of Contents

Site settings

settings is the first argument to baseline(). It carries site identity: title, tagline, canonical URL, indexability, languages, and any extra <head> items you want injected on every page.

Settings flow through state.settings and surface in templates as _pageContext.site (and as settings in the data cascade when you keep them in _data/settings.js).


The settings shape

export default {
	title: 'Your site',
	tagline: 'A short site-wide line.',
	description: 'What the site is, for pages that do not say.',
	url: 'https://www.example.com',
	noindex: false,
	defaultLanguage: 'en',
	languages: { en: {}, fr: {} },
	head: {
		link: [],
		script: [],
		meta: [],
		style: []
	},
	seo: {
		preserveQueryParams: false,
		ogImage: null,
		openGraph: {},
		twitter: {}
	}
};

await eleventyConfig.addPlugin(baseline(settings));

Every key is optional. Baseline logs a warning if settings.url is missing, and then the head emits no canonical, no Open Graph or Twitter tags and no JSON-LD, rather than guessing an origin. The sitemap is the one exception: it still renders, with relative <loc> values.

A value that is not an absolute http(s) URL is dropped and behaves exactly like a missing one, with the warning naming the value it ignored. A path on the origin is accepted, but see deploying under a subpath before putting one there.

settings.url is the only place Baseline reads a site origin from. It anchors canonicals, sitemap entries, structured data, and the link rewriting HtmlBasePlugin does in your pages. Keep it origin-only and put subpaths in pathPrefix. Which environment variable it comes from is your choice, since nothing in the plugin reads the environment for it.


Keys

Key Type What it does
title string Site title. Used by the head module to compose <title> (Page title – Site title) and by the navigator template.
tagline string Short site-wide line, used as the home page's title suffix. It is not a description fallback; description is.
description string Site-wide description. The last rung of the <meta name="description"> chain, used when a page supplies no seo.description, description or excerpt of its own.
url string Absolute site URL including protocol. Resolves canonical URLs, sitemap entries, Open Graph tags and the JSON-LD graph. Baseline warns at startup if it is missing, and warns again naming the value if it is not an absolute http(s) URL. The image shortcode does not read it: it emits root-relative /media/ paths, and making one absolute is yours to do.
noindex boolean Default false. When true, every page renders <meta name="robots" content="noindex, nofollow">, canonicals are dropped, and the sitemap renders with no entries in it. Useful for staging. A page can also set noindex: true in its own front matter.
defaultLocale string BCP 47 default locale ('en-US'), and the preferred key. Sets the site's default language and the fallback page.locale for pages whose language has no locale of its own. This or defaultLanguage is required for multilingual activation.
defaultLanguage string Short language code ('en'), a writer-side alias for defaultLocale: set it when you do not need a region and Baseline derives the locale from it. Either key serves every consumer. All of them assume default-language URLs are unprefixed and every other language sits under /<lang>/; writing those permalinks is still yours.

The languages map

object or string[]. Object form { en: {}, fr: {} }, or array shorthand ['en', 'fr'] which is normalised to objects with empty entries. Invalid entries are dropped, and logged when verbose: true. Required for multilingual activation.

Baseline reads six keys off an entry:

Key What it does
title, tagline, description Per-language overrides of the site-level values, read into _pageContext.site for pages in that language.
locale The BCP 47 tag ('en-US') that becomes page.locale for pages in that language.
languageName The language's name in its own language. Becomes the label on each entry in page.translations and in collections.translationsMap, which is what a language switcher renders. Falls back to the language code.
homeLabel The label for the first breadcrumb crumb in that language. Falls back to Home.
export default {
	languages: {
		en: { title: 'Your site', tagline: 'A short line.', locale: 'en-US', languageName: 'English', homeLabel: 'Home' },
		fr: { title: 'Votre site', tagline: 'Une ligne courte.', locale: 'fr-FR', languageName: 'Français', homeLabel: 'Accueil' }
	}
};

Anything else you put on an entry rides through untouched and is yours to read as settings.languages[lang]. contentDir, the folder that language's content sits in, is the convention worth knowing: the plugin never reads it, and it exists so a switcher, or anything else that needs to find a language's content, has one place to ask.


The head extras

object. Additive <head> entries injected on every page. Four arrays, one per element type, and each entry is an object whose keys become attributes on the rendered tag.

export default {
	head: {
		link: [
			{ rel: 'stylesheet', href: '/assets/css/index.css' },
			{ rel: 'icon', href: '/favicon.svg' }
		],
		script: [{ src: '/assets/js/index.js', defer: true }],
		meta: [{ name: 'theme-color', content: '#0a0a0a' }],
		style: []
	}
};

Pages can add their own entries through the same shape in front matter; Baseline merges and deduplicates. See the head module for the merge rules.

This is also where you wire the asset pipeline into your pages. Baseline compiles assets/css/index.css and assets/js/index.js to /assets/css/index.css and /assets/js/index.js at the site root, but it does not auto-inject them. Declare a link and a script entry as above. The default docs site does exactly this.

Output filenames are unhashed today. Cache-busting via hashed filenames is on the roadmap, and the entrypoint declaration shape may change to accommodate it.

In practice link, script and meta carry almost everything you need. style is supported for parity but rarely used; inline <style> blocks usually belong in your CSS pipeline rather than the head extras list.


The seo defaults

object. Site-wide SEO defaults, feeding the resolved seo namespace and the payload the head module emits: canonical, Open Graph, Twitter Card, JSON-LD. All optional.

export default {
	seo: {
		// keep the query string on canonical URLs (default: strip it)
		preserveQueryParams: false,
		// default share card; the url must be absolute (it lands in the JSON-LD graph)
		ogImage: { url: 'https://www.example.com/og.jpg', width: 1200, height: 630, alt: '' },
		// default Open Graph and Twitter values, overridable per page
		openGraph: { type: 'website' },
		twitter: { card: 'summary_large_image', site: '@yoursite', creator: '@you' }
	}
};

Four keys live inside those last two objects:

Key Default What it does
openGraph.type website The og:type for pages that are not articles. A page with type: article projects article regardless.
twitter.card summary_large_image The twitter:card for every page.
twitter.site none The site's handle. Overridable per page with seo.twitterSite.
twitter.creator none The account the whole site is credited to. No per-page override, so it is site-wide by design.

The share image default lives here, in settings.seo, because it is page presentation: the same shelf as og:type and twitter:card. Identity images, an organisation logo or a person's photo, live in the schema cascade key instead, because they are properties of the entity.

This default is a social fallback and stays one. It fills og:image and twitter:image on every page, and it does not become the page's primaryImageOfPage in the graph, which would be a claim that a single site-wide card is the image representing each page. Set ogImage on a page and that page gets both. A site-wide card alone gets you the share image and no graph claim.

Keep the url absolute. It lands in the JSON-LD graph, inside a <script> that Eleventy's HtmlBasePlugin never walks, so a root-relative path ships exactly as you wrote it while the @id beside it is absolute. Baseline warns once per relative url rather than rewriting it.

A page that should carry no share image at all sets ogImage: false. That declines it outright and does not inherit the site default.


SEO front matter

Beyond settings.seo, a page carries its own SEO through front-matter keys. Baseline reads them into the resolved SEO values and the JSON-LD graph the head module emits. Each is optional; a page with none still gets a complete, valid graph from the site defaults.

Key Type What it does
ogImage string, object or false Per-page share card, and the only source of the graph's primaryImageOfPage. Overrides settings.seo.ogImage for og:image. Object form { url, width, height, alt } lets the graph emit a sized ImageObject; a bare string emits a url-only og:image and no node. false declines a share image on this page, so nothing is emitted and the site default is not inherited.
canonical string Explicit canonical URL. Without it the canonical is the page's own absolute URL.
preserveQueryParams boolean Keep the query string on this page's canonical. Overrides the site default. The fragment is always stripped.
pageType string Overrides the WebPage node's schema.org @type (e.g. AboutPage, CollectionPage).
articleType string Overrides the Article node's @type (e.g. BlogPosting). Takes effect only when the page is an article (type: article).
topics string or string[] Keyword classification. Emitted as schema.org keywords on the WebPage and Article nodes, and as og:article:tag on article pages. Separate from Eleventy's native tags, which Baseline leaves alone. Bring your own taxonomy: if you want topic-listing pages, build a collection from topics yourself.
sectionLabel string Display name for the page's section. On an article page it becomes schema.org articleSection and og:article:section; elsewhere nothing reads it. Usually set once in a directory data file rather than per page.
datePublished string Publish date for the structured data. Defaults to the page's date. Sets datePublished on the WebPage and Article nodes.
dateModified string Last-modified date for the structured data. Resolves front matter first, then the git last-commit date, then the publish date. Sets dateModified.

Under a seo: key

The keys above sit at the top level of the front matter. A second set sits inside a seo: object, and those are the ones that overrule a specific tag rather than describe the page:

---
title: 'About us'
seo:
    ogTitle: 'The people behind the thing'
    twitterCard: 'summary'
---
Key Type What it does
seo.title string Overrules the page title everywhere the title is composed, <title> and the graph included. title in front matter is the usual place to set this.
seo.description string The same for the description. First rung of the <meta name="description"> chain.
seo.ogTitle string og:title alone, leaving <title> and the graph as they were.
seo.ogDescription string og:description alone.
seo.ogType string og:type for this page, over everything else, including the article that a page with type: article would otherwise project.
seo.twitterCard string twitter:card. Defaults to summary_large_image from settings.seo.twitter.card.
seo.twitterSite string twitter:site for this page, over the site-wide handle.
seo.twitterTitle string twitter:title, emitted only when it differs from the Open Graph title. Twitter reads the OG tags otherwise, so a duplicate is noise.
seo.twitterDescription string twitter:description, on the same terms.
seo.twitterImage string twitter:image, on the same terms.
seo.canonical string The seo: spelling of canonical above. Either place works, and this one wins.
seo.noindex boolean The seo: spelling of noindex. Either place works, and this one wins, including when it sets false against a bare noindex: true inherited from a directory data file.
seo.ogImage string The seo: spelling of ogImage. Here the top-level one wins, and only this one takes a bare url, so ogImage is the better place for both.

The Twitter three are deliberately quiet: Twitter falls back to the Open Graph tags when a twitter: equivalent is missing, so Baseline emits one only where you have said something different.

Identity authoring, your organisation and author profile plus any extra schema.org nodes, lives in the schema cascade key rather than per-page front matter.


Multilingual activation

Three things must be set together: options.multilingual: true, settings.defaultLocale or settings.defaultLanguage, and a non-empty settings.languages. Nothing is inferred. If any of the three is missing, the multilang module skips activation and logs why.

See the multilang module for what activation enables (per-language collections, hreflang, translation filters).


Where settings surface

Surface Reads
_pageContext.site title, tagline, description, url, noindex (per-language overrides if present)
_pageContext.meta composed <title>, default description from description, robots from noindex
Head module head.{link, script, meta, style} extras
seo namespace url; seo defaults: canonical policy, share image, Open Graph and Twitter values
Sitemap module url, noindex (empty sitemap when true); defaultLanguage and languages for per-lang sitemaps
Multilang module defaultLocale or defaultLanguage, languages
Breadcrumbs languages[lang].homeLabel for the first crumb

See also