Astro: Adding Meta Tags from Child Components

Founder and CEO
Sometimes, certain pages require additional meta tags based on their context. In our case, we needed to include a meta tag for Atom feed auto-discovery, but only on pages related to the company blog. This meant injecting a meta tag from a child component into the parent layout component. While there are a few ways to handle this, in this blog post, we will discuss a clean approach using Astro’s named slots feature.
The concept of slots is simple and widely used across UI libraries and frameworks. A slot is just a placeholder inside a component where child content gets injected. Perhaps the most common use case is separating the application layout from the content page structure. Astro extends this concept by allowing components to define multiple named slots, enabling flexible component structure. With this feature, child components can target specific areas of their parent component by injecting content into these named slots.
Let’s see it in action. Suppose there is a BaseLayout
component with two slots: a named slot called “meta” and an unnamed default slot.
The default slot receives all child component elements that aren’t explicitly assigned to a named slot.
BaseLayout.astro
---
const { title } = Astro.props;
---
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
{/* slot for additional meta tags */}
<slot name="meta" />
<title>{title}</title>
</head>
<body>
<slot />
</body>
</html>
A child component can inject content into a named slot by using the slot attribute. Here’s an example of a child blog post layout component doing just that.
BlogPostLayout.astro
---
const { frontmatter } = Astro.props;
---
<BaseLayout title={frontmatter.title}>
{/* this element will be injected into the "meta" slot */}
<link slot="meta" rel="alternate" type="application/atom+xml" href="/path/to/atom-feed" />
{/* this element will be injected into the default slot */}
<main class="...">
<header>
<h1 class="...">{frontmatter.title}</h1>
</header>
<article class="...">
{/* default slot of this component: commonly injected via a markdown processor */}
<slot />
</article>
</main>
</BaseLayout>
But suppose you have more than one element to inject into the same slot. Astro allows multiple elements to be injected into the same named slot. Here’s an example including both Atom and RSS feeds. Astro will inject both elements into the same “meta” slot in the order they appear.
<BaseLayout title={frontmatter.title}>
<link slot="meta" rel="alternate" type="application/atom+xml" href="/path/to/atom-feed" />
<link slot="meta" rel="alternate" type="application/rss+xml" href="/path/to/rss-feed" />
</BaseLayout>
Alternatively, you can group multiple elements using Astro’s Fragment component. This is the officially documented way to inject multiple elements into a single named slot.
<BaseLayout>
<Fragment slot="meta">
<link rel="alternate" type="application/atom+xml" href="/path/to/atom-feed" />
<link rel="alternate" type="application/rss+xml" href="/path/to/rss-feed" />
</Fragment>
</BaseLayout>
This pattern keeps your components modular and your layouts clean, while allowing page-specific meta tags to be defined where they logically belong. It is a simple, effective approach that fits naturally into Astro’s component model. While this post focuses on meta tags and our specific use case, this is just one way to use slots.