このサイトのベーステーマには、Astro Boilerplateを使用しています。
このテーマは、記事にタグを付与する事は可能ですが、タグ一覧ページや、タグ別のページを表示する機能を装備していません。そのため、自分で調べて実装してみようと思います。
例えば、何らかのキーワードで検索して、とあるサイトに訪れたとしましょう。例えば・・・、そうですね。キーワードは Astro にしましょう。
とあるサイトのAstroに関する記事を読んで、その人が執筆する別のAstroの記事が気になった場合、どのように検索をすれば良いでしょうか。検索方法はいくつかあります。
etc…
これらの方法はどれも読み手が行う必要があります。まあそうですよね。こちら側では何も用意していないんですから。
つまり、よりサイトを回游してもらうためには、タグ分けやカテゴリ分けは必要と考えます。
Astroの公式ドキュメントに、タグページの生成 について書かれているので、 これに則りながら、なるべく Astro Boilerplate が用意してくれているコンポーネントを使用して実装してみます。
タグが付与された記事が無い事には何も始まりません。適当にタグを付与します。
---
layout: '@/templates/BasePost.astro'
title: 【Astro】 Astro Boilerplateにタグ一覧ページを実装してみる
description:
pubDate: 2024-01-07T00:00:00Z
imgSrc: '/assets/images/11/11.avif'
imgAlt: '11'
+ tags: [Astro]
---
私は下記のように実装してみました。色合いなどは、サイトに応じて調整して下さい。
src/partials/TagCard.tsx
type ITagCardProps = {
tagName: string;
imgSrc: string;
imgAlt: string;
};
const TagCard = (props: ITagCardProps) => (
<a className="hover:translate-y-1" href={`/tags/${encodeURIComponent(props.tagName)}/`}>
<div className="overflow-hidden rounded-md bg-slate-800">
<div className="aspect-w-3 aspect-h-2">
<img
className="h-full w-full object-cover object-center"
src={props.imgSrc}
alt={props.imgAlt}
loading="lazy"
/>
</div>
<div className="px-3 pt-4 pb-6 text-center">
<h2 className="text-xl font-semibold">
{props.tagName}
</h2>
</div>
</div>
</a>
);
export { TagCard };
src/partials/TagGallery.tsx
import { TagCard } from './TagCard';
type ITagGalleryProps = {
tagList: { tagName: string; imgSrc: string; imgAlt: string; }[];
};
const TagGallery = (props: ITagGalleryProps) => (
<div className="tags">
<div className="grid grid-cols-1 gap-6 md:grid-cols-3">
{props.tagList.map((tag, index) => (
<TagCard key={index} {...tag} />
))}
</div>
</div>
);
export { TagGallery };
Astro Boilerplate の 記事一覧 (All Posts) ページと同じデザインになっています。
タグの文字だけだと寂しいかなと思い、記事と同じようにサムネイルを表示するようにしています。サムネイル画像は、/assets/images/tags/${tag}.avif
のような形で配置するようにしています。
src/pages/tags/index.astro
---
import type {
IFrontmatter,
} from 'astro-boilerplate-components';
import {
PaginationHeader,
Section,
} from 'astro-boilerplate-components';
import { TagGallery } from '@/partials/TagGallery';
import { CTA } from '@/partials/CTA';
import Base from '@/templates/Base.astro';
import { AppConfig } from '@/utils/AppConfig';
const allPosts = await Astro.glob<IFrontmatter>('../posts/*.md');
const tags = [...new Set(allPosts.filter((post) => post.frontmatter.tags !== undefined).map((post) => post.frontmatter.tags).flat())];
const tagList = Array.from(tags).map(tag => ({
tagName: tag,
imgSrc: `/assets/images/tags/${tag}.avif`,
imgAlt: tag
}));
const title = `All Tags - ${AppConfig.site_name}`;
const description = `All Tags - ${AppConfig.site_name}`;
---
<Base head={{ title, description }}>
<Section>
<PaginationHeader
title='All Tags'
description=''
/>
</Section>
<Section>
<TagGallery tagList={tagList} />
</Section>
<CTA />
</Base>
タグでフィルタした記事一覧ページです。
src/pages/tags/[tag].astro
---
import {
BlogGallery,
NewerOlderPagination,
PaginationHeader,
Section,
} from 'astro-boilerplate-components';
import Base from '@/templates/Base.astro';
import { CTA } from '@/partials/CTA';
import { AppConfig } from '@/utils/AppConfig';
export async function getStaticPaths() {
const allPosts = await Astro.glob('../posts/*.md');
const postsWithTags = allPosts.filter((post) => post.frontmatter.tags);
const uniqueTags = [...new Set(postsWithTags.map((post) => post.frontmatter.tags).flat())];
return uniqueTags.map((tag) => {
const filteredPosts = postsWithTags.filter((post) => post.frontmatter.tags.includes(tag));
return {
params: { tag },
props: { posts: filteredPosts },
};
});
}
const { tag } = Astro.params;
const { posts } = Astro.props;
const title = `${tag} - ${AppConfig.site_name}`;
const description = `${tag} - ${AppConfig.site_name}`;
---
<Base head={{ title, description }}>
<Section>
<PaginationHeader title={tag} description='' />
</Section>
<Section>
<BlogGallery postList={posts} />
</Section>
<CTA />
</Base>
以上で完了です。このコードは、この記事執筆時点での私のサイトのタグ機能です。 ページ上部の Tags 以下が、このコードによって形成されています。ぜひ遷移してみて下さい。
しかし、タグ機能としてはまだ不完全です。記事に付与したタグ情報はタグページを生成するためだけにしか使用していないためです。
記事の上部、または最下部に、タグ情報を表示する事で、読者の回游に繋がると考えます。その機能はまた、モチベーションがある時にでも実装してみます。