Skip to content

Tags

Tags are short, specific keywords attached to blog posts. They describe what a post is about at a fine-grained level — astro, contact form, template, seo, and so on.

Every tag you add to a post frontmatter automatically creates a tag archive page at /tags/<tag>/. That page lists every post that uses the tag. No manual configuration needed.

Tags are one of the two ways to organize blog content in Astro Docus. The other is categories, which are broader and coarser-grained.


Tags are not stored in a separate file. They live inside the frontmatter of every blog post:

tags: ["astro", "contact form", "astro template", "astro themes"]

The tag system reads every blog post, collects all tags, and builds:

  • A tag index page at /tags/ — lists every tag in use
  • A tag archive page at /tags/<tag>/ — lists every post with that tag

Both are generated automatically.


The tag index lives at src/pages/tags/index.astro:

---
import BaseLayout from "../../design/base.astro";
import Data from "../../data/configuration/blog/blogpage.json";
const allPosts = Object.values(import.meta.glob("../blog/*.md", { eager: true })) as any[];
const tags = [...new Set(allPosts.map((blog) => blog.frontmatter.tags).flat().filter(Boolean))];
const pageTitle = "Tag Index";
---
<BaseLayout pageTitle={pageTitle}>
<div class="col-md-12 p-3 text-center">
<h1><strong><a href={Astro.url}>{Data.tags_page_title}</a></strong></h1>
<h2>{Data.tags_page_description} Tags article</h2>
</div>
<div class="row mt-5">
{tags.map((tag: any) => (
<h3 class="col-md-4 p-3"><a href={`/tags/${tag}`}>{tag}</a></h3>
))}
</div>
</BaseLayout>
  1. Loads every blog post — import.meta.glob("../blog/*.md", { eager: true }) reads all .md files in src/pages/blog/ at build time.
  2. Extracts all tags — maps over every post, takes frontmatter.tags, flattens the arrays, and filters out empty values.
  3. Deduplicates — new Set(...) removes duplicates so each tag appears once.
  4. Renders the list — loops through unique tags and displays each as a link to /tags/<tag>/.
  5. Reads page title and description — from blogpage.json (tags_page_title and tags_page_description).

A simple page listing every tag used across your blog. Clicking any tag goes to that tag’s archive.


Each tag has its own page generated dynamically by src/pages/tags/[tag].astro:

---
import BaseLayout from "../../design/tags.astro";
import BlogPost from "../../widget/BlogPost.astro";
export async function getStaticPaths() {
const allPosts = Object.values(import.meta.glob("../blog/*.md", { eager: true })) as any[];
const uniqueTags = [...new Set(allPosts.map((post) => post.frontmatter.tags).flat())];
return uniqueTags.map((tag) => ({
params: { tag },
props: { posts: allPosts.filter((post) => post.frontmatter.tags?.includes(tag)) },
}));
}
const { tag } = Astro.params;
const { posts } = Astro.props as any;
---
<BaseLayout pageTitle={tag}>
<div class="col-md-12 p-3 text-center">
<h1>{tag}</h1>
<h2 class="lead">List of tags for {tag}</h2>
</div>
{posts.map((post: any) => (
<BlogPost url={post.url} title={post.frontmatter.title} description={post.frontmatter.description} image={post.frontmatter.image} />
))}
</BaseLayout>
  1. getStaticPaths() — runs at build time. It reads every blog post, collects unique tags, and generates one page per tag.
  2. For each tag, it filters all posts to find only those that include the tag.
  3. Astro.params.tag — the current tag being rendered (from the URL).
  4. Astro.props.posts — the list of posts for this tag.
  5. Renders each post using the <BlogPost /> widget.

Each tag gets its own page at /tags/<tag>/, listing all posts with that tag. For example, /tags/astro/ lists every post tagged astro.


Tags are added in the frontmatter of any blog post:

---
layout: ../../design/blog/blogpost.astro
title: "My Post"
description: "Short summary"
image: /src/assets/cover.png
pubDate: 2025-01-15
tags: ["astro", "tutorial", "seo"]
categories: ["guides"]
---

The tags array can contain any number of tags. Once saved, the tag archive pages for astro, tutorial, and seo are regenerated automatically at the next build.

  • Lowercase — astro, not Astro
  • Short phrases — contact form, not how to build a contact form
  • Consistent spelling — if you use seo in one post, do not use SEO or search-engine-optimization in another
  • No duplicates — ["astro", "astro"] is redundant
  • No empty strings — the tag index filters them out, but they clutter your frontmatter

The tag index reads from src/data/configuration/blog/blogpage.json:

"tags_page_title": "Tags Astro Themes",
"tags_page_description": "Update blog Docus Astro JS Starlight Themes template with complete features - tagging"

Edit those values to change the title and description on /tags/.

The tag archive uses src/design/tags.astro as its layout. Edit that file to change how individual tag pages look.

Each post in a tag archive is rendered by <BlogPost /> from src/widget/BlogPost.astro. Edit that widget to change how posts appear in the list.


TagsCategories
SpecificBroad
Many per postFew per post
astro, contact form, seotutorial, news
Fine-grained discoveryHigh-level grouping
URL: /tags/<tag>/URL: /categories/<category>/

You can use both on the same post. A post about setting up a contact form might have:

tags: ["astro", "contact form"]
categories: ["tutorial"]

Tags help readers find related content. Categories help them browse by section.


  1. Tags live in post frontmatter — no separate config file.
  2. The tag index and archives are auto-generated — no manual listing.
  3. Keep spelling consistent — inconsistent tags create duplicate archives.
  4. Use lowercase — for cleaner URLs and sorting.
  5. Do not rename tags lightly — renaming a tag creates a new archive and breaks existing links.
  6. Empty tag arrays are fine — posts without tags simply do not appear in any tag archive.

Blog post frontmatter:
tags: ["astro", "contact form", "seo"]
│
▼
/tags/ → index of all tags
/tags/astro/ → all posts tagged "astro"
/tags/contact form/ → all posts tagged "contact form"
/tags/seo/ → all posts tagged "seo"

Files involved:

FilePurpose
src/pages/tags/index.astroTag index page
src/pages/tags/[tag].astroIndividual tag archive
src/design/tags.astroTag archive layout
src/widget/BlogPost.astroPost card in archives
src/data/configuration/blog/blogpage.jsonTag index title/description

Add a tag — edit a post’s frontmatter. That’s it. Everything else is automatic.