Tags
What Are Tags?
Section titled “What Are 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.
Where Tags Live
Section titled “Where Tags Live”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.
How the Tag Index Works
Section titled “How the Tag Index Works”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>What it does
Section titled “What it does”- Loads every blog post —
import.meta.glob("../blog/*.md", { eager: true })reads all.mdfiles insrc/pages/blog/at build time. - Extracts all tags — maps over every post, takes
frontmatter.tags, flattens the arrays, and filters out empty values. - Deduplicates —
new Set(...)removes duplicates so each tag appears once. - Renders the list — loops through unique tags and displays each as a link to
/tags/<tag>/. - Reads page title and description — from
blogpage.json(tags_page_titleandtags_page_description).
The result
Section titled “The result”A simple page listing every tag used across your blog. Clicking any tag goes to that tag’s archive.
How a Tag Archive Works
Section titled “How a Tag Archive Works”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>What it does
Section titled “What it does”getStaticPaths()— runs at build time. It reads every blog post, collects unique tags, and generates one page per tag.- For each tag, it filters all posts to find only those that include the tag.
Astro.params.tag— the current tag being rendered (from the URL).Astro.props.posts— the list of posts for this tag.- Renders each post using the
<BlogPost />widget.
The result
Section titled “The result”Each tag gets its own page at /tags/<tag>/, listing all posts with that tag. For example, /tags/astro/ lists every post tagged astro.
Adding Tags to a Post
Section titled “Adding Tags to a Post”Tags are added in the frontmatter of any blog post:
---layout: ../../design/blog/blogpost.astrotitle: "My Post"description: "Short summary"image: /src/assets/cover.pngpubDate: 2025-01-15tags: ["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.
Rules for tags
Section titled “Rules for tags”- Lowercase —
astro, notAstro - Short phrases —
contact form, nothow to build a contact form - Consistent spelling — if you use
seoin one post, do not useSEOorsearch-engine-optimizationin another - No duplicates —
["astro", "astro"]is redundant - No empty strings — the tag index filters them out, but they clutter your frontmatter
Editing the Tag Pages
Section titled “Editing the Tag Pages”Change the tag index heading
Section titled “Change the tag index heading”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/.
Change the tag archive layout
Section titled “Change the tag archive layout”The tag archive uses src/design/tags.astro as its layout. Edit that file to change how individual tag pages look.
Change the tag archive post rendering
Section titled “Change the tag archive post rendering”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.
How Tags Differ From Categories
Section titled “How Tags Differ From Categories”| Tags | Categories |
|---|---|
| Specific | Broad |
| Many per post | Few per post |
astro, contact form, seo | tutorial, news |
| Fine-grained discovery | High-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.
Rules to Remember
Section titled “Rules to Remember”- Tags live in post frontmatter — no separate config file.
- The tag index and archives are auto-generated — no manual listing.
- Keep spelling consistent — inconsistent tags create duplicate archives.
- Use lowercase — for cleaner URLs and sorting.
- Do not rename tags lightly — renaming a tag creates a new archive and breaks existing links.
- Empty tag arrays are fine — posts without tags simply do not appear in any tag archive.
Quick Recap
Section titled “Quick Recap”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:
| File | Purpose |
|---|---|
src/pages/tags/index.astro | Tag index page |
src/pages/tags/[tag].astro | Individual tag archive |
src/design/tags.astro | Tag archive layout |
src/widget/BlogPost.astro | Post card in archives |
src/data/configuration/blog/blogpage.json | Tag index title/description |
Add a tag — edit a post’s frontmatter. That’s it. Everything else is automatic.