Skip to content

Tag list

Implementation in Starlight

  1. Create TagList component

    src/components/TagList.astro
    ---
    import { getCollection } from "astro:content";
    const docs = await getCollection("docs");
    type Docs = typeof docs;
    const docsByTags = new Map<string, Docs>();
    docs.forEach((doc) => {
    if (doc.data.tags) {
    doc.data.tags.forEach((tag: string) => {
    docsByTags.set(tag, docsByTags.get(tag) || []);
    docsByTags.get(tag)?.push(doc);
    });
    }
    });
    const comparator = new Intl.Collator("en");
    const tagsSorted = [...docsByTags.keys()].sort(comparator.compare);
    ---
    <ul>
    {
    tagsSorted.map((tag) => (
    <li>
    {tag} ({docsByTags.get(tag)?.length})
    <ul>
    {docsByTags.get(tag)?.map((doc) => (
    <li>
    <a href={`/${doc.slug}`}>{doc.data.title}</a>
    </li>
    ))}
    </ul>
    </li>
    ))
    }
    </ul>
  2. Adjust content schema

    src/content/config.ts
    import { z, defineCollection } from "astro:content";
    import { docsSchema, i18nSchema } from "@astrojs/starlight/schema";
    export const collections = {
    docs: defineCollection({
    schema: docsSchema({
    extend: z.object({
    tags: z.array(z.string()).optional(),
    }),
    }),
    }),
    i18n: defineCollection({ type: "data", schema: i18nSchema() }),
    };
  3. Use component, wherever you like

    ---
    title: Tags
    tableOfContents: false
    prev: false
    next: false
    ---
    import TagList from "@components/TagList.astro";
    <TagList />

Example

See Tags.

Further improvements

  • page for each tag
  • metadata for tags (color, icon)

Tag page

From starlight-blog:

Icons for tags

Each tag can have it’s own color or icon, to help differentiate them visually, for example: #markdown , #component , #link , #page , #Astro , #TypeScript