---
title: 'Head and NoIndex'
description: 'Set Baseline head defaults, add per-page head extras and block robots.'
slug: 'head-and-noindex'
type: 'article'
date: 2026-04-28T00:00:00.000Z
lang: 'en'
url: 'https://www.eleventy-baseline.dev/docs/feature-guide/head-and-noindex/'
---

Get a clean, correct `<head>` on every page with one placeholder and a settings file. By the end you'll have site-wide metadata, per-page head extras flowing through `settings.head` and front matter, and a proper canonical and robots story.

Hreflang is covered in the [[multilingual-baseline-site | multilingual site]] tutorial. The placeholder is the only piece of HTML you write yourself.

{% alertBlock %}

The placeholder, `<baseline-head>`, is the element your layout puts on the page.

Baseline swaps it for a sorted, deduplicated `<head>` at transform-time, the stage of the build where Eleventy hands rendered HTML to plugins for last-mile mutation.

The data that fills it (title, description, canonical, links, scripts, hreflang) is gathered earlier, at cascade-time, when Eleventy is computing each page's data.

Two stages, one placeholder.

{% endalertBlock %}

---

## What you will build

- A page rendered with proper `title` and `description`.
- Canonical and robots tags written automatically.
- Site-wide and per-page head extras through `link[]`, `script[]`, `meta[]`.
- Noindex controls at both site and page level.
- A neatly organised `<head>`, thanks to Capo.js.

---

## Prerequisites

- Baseline already installed and loaded, as in the [[simple-baseline-site | simple site tutorial]].
- Set `settings.url` to your production URL (or leave localhost for local testing).
- `package.json` with `"type": "module"` and the `dev`/`build` scripts:
  ```json
  {
  	"name": "simple-baseline-site",
  	"type": "module",
  	"scripts": {
  		"start": "rimraf dist/ && npx @11ty/eleventy --serve",
  		"build": "rimraf dist/ && cross-env ELEVENTY_ENV=production npx @11ty/eleventy"
  	}
  }
  ```

---

## 1) Ensure Baseline is loaded

`eleventy.config.js`:

```js
import baseline, { config as baselineConfig } from '@apleasantview/eleventy-plugin-baseline';
import settings from './src/_data/settings.js';

/** @param {import("@11ty/eleventy").UserConfig} eleventyConfig */
export default async function (eleventyConfig) {
	await eleventyConfig.addPlugin(
		baseline(settings, {
			head: {
				titleSeparator: ' | ',
				showGenerator: true
			}
		})
	);
}

export const config = baselineConfig;
```

Two head options are worth knowing about:

{% stepsBlock "compact" %}

`titleSeparator` controls how the page title and site title are joined. Defaults to `–` (en-dash with surrounding spaces).

`showGenerator` adds a `<meta name="generator">` tag. Off by default; flip it on if you want the credit visible in production.

{% endstepsBlock %}

---

## 2) Site-wide metadata

Update `src/_data/settings.js`. The fields below are the source of truth for what Baseline writes into every page's head:

```js
export default {
	title: 'Baseline Head Demo',
	tagline: 'Head quickstart',
	url: process.env.URL || 'http://localhost:8080/',
	defaultLanguage: 'en',
	noindex: false,

	head: {
		link: [
			{ rel: 'stylesheet', href: '/assets/css/index.css' },
			{ rel: 'me', href: 'https://mastodon.social/@yourhandle' }
		],
		script: [{ src: '/assets/js/index.js', defer: true }],
		meta: [{ name: 'color-scheme', content: 'light dark' }]
	}
};
```

Each entry in `link[]`, `script[]`, and `meta[]` becomes an element on every page, alongside the defaults Baseline writes itself (charset, viewport, title, description, canonical, robots).

---

## 3) Layout with the placeholder

Create `src/_includes/layouts/base.njk`. Baseline replaces `<baseline-head></baseline-head>` with the rendered `<head>` at build time. It sits as a sibling of `<body>`, never inside a `<head>` of your own.

If the placeholder is missing, Baseline quietly skips the replacement and nothing is injected. Refer to the minimal layout in the [[simple-baseline-site|simple site tutorial]].

---

## 4) Page front matter

Create `src/content/pages/head-demo.md`:

```md
---
title: 'Head Demo'
slug: 'head-demo'
description: 'A page showing Baseline head defaults.'
layout: 'layouts/base.njk'
---

This page uses Baseline's head defaults for canonical and robots. The title and description in the front matter become the rendered `<title>` and `<meta name="description">`.
```

---

## 5) Per-page head overrides

A page's own front matter can extend or override the site-wide head. Add this block to `src/content/pages/head-demo.md`:

```yaml
head:
  meta:
    - { name: 'description', content: 'Override description for this page' }
  link:
    - { rel: 'author', href: 'https://yourdomain.com' }
```

Baseline computes the canonical URL from `page.url` and `settings.url`, stripping the query string and fragment. If `settings.url` is missing, no canonical is emitted (baseline warns at startup).

To override the canonical per page, set a top-level `canonical` field in front matter. See the SEO front-matter table in [[site-settings | Site settings]].

Open Graph and Twitter card tags are emitted automatically from `settings.seo` and per-page front matter; you no longer hand-roll them as `head.meta[]` entries.

---

## 6) Noindex (site-wide and per-page)

Three knobs, in widening order of scope:

{% stepsBlock "compact" %}

Site-wide: set `noindex: true` in `_data/settings.js`. Every page gets a `robots` noindex tag, and the sitemap is skipped entirely.

Per-page: set `noindex: true` in front matter. The page renders a `robots` noindex tag and drops out of the sitemap.

Sitemap-only: set `sitemap: { ignore: true }` in front matter. The page renders normally; only the sitemap entry is removed.

{% endstepsBlock %}

The relationship is deliberate: `noindex` is the broader signal (don't index, don't list), `sitemap.ignore` is the narrow one (just don't list).

---

## 7) Run and inspect

```bash
npm start
```

- Open `/head-demo/` (default http://localhost:8080/head-demo/).
- View source. Confirm the placeholder is gone, the canonical (or your override) is in, and the defaults for description and robots are rendered.
- Check `dist/sitemap.xml` while dev runs. The page should appear unless `noindex` is true.

---

## 8) Production build

Change `URL` in `.env` to an absolute URL. On a deployed site that's your real production URL; for this exercise, any absolute URL (e.g. `https://www.example.com/`) works to verify the output. Then run:

```bash
npm run build
```

- Inspect `dist/head-demo/index.html` for the rendered head.
- Confirm `dist/sitemap.xml` includes or excludes the page in line with `noindex`.
- Reset `URL` in `.env` to "http://localhost:8080/".

---

## Next steps

- Add custom `head.link[]`, `head.script[]`, or `head.meta[]` entries through `_data/settings.js` or per-page front matter.
- For the full multilingual setup, see the [[multilingual-baseline-site | multilingual site tutorial]] and the [[head | head module reference]].
