An expected feature of a Blog site, is to have some way to list posts by selecting a tag
, which is a keyword or concept that is talked about often or in several posts. This post you are reading has been tagged with: {frontmatter.tagsAlt}.
Click here to go to all posts tagged astro
. You can click on each post’s tag-list to switch to that tag.
Here is the whole page code that works on v0.26.0+
, including beta
.
/* /src/pages/blog/tag-post/[tag].astro */
---
import BaseLayout from './../../../layouts/BaseLayout.astro';
export async function getStaticPaths () {
// grab all .md files from a folder
let allPosts = await Astro.glob('./../*.md');
// I need this filter to ignore files that do not have
// a title, or no published date (in frontmatter)
// this way I leave the date out while the post is not finished.
let filteredPosts =
allPosts.filter((p) => {
return p.frontmatter.title && p.frontmatter.published;
});
// an object to collect existing tags
let dix = {};
filteredPosts.forEach((post) => {
// go thru each tag in each published post,
// fill in the object...
post.frontmatter.tags.forEach((tag) => {
if (!dix[tag]) dix[tag] = 0;
dix[tag] += 1;
});
});
console.log('dix', dix); // <-- prints out our tag-cloud data.
let ary = [];
// format the data to return from getStaticPaths()
for (let prop in dix) {
ary.push({
params: { tag: prop.replace(/:/g, '') },
props: { tagname: prop, count: dix[prop] }
});
}
return ary;
}
// grab the selected tag from the url (dynamic [tag])
const tagname = Astro.params.tag;
const tagcount = Astro.props.count;
// These section feels duplicated from getStaticPaths()
// opportunity to refactor...
let allPosts = await Astro.glob('./../*.md');
let filteredPosts =
allPosts.filter((p) => {
return p.frontmatter.title && p.frontmatter.published;
});
// now filter to only posts containing the selected tag,
// these will be rendered below in the markup.
let tagged = filteredPosts.filter((p) => {
return p.frontmatter.tags.includes(tagname);
});
---
<BaseLayout title="The Blog - tag list example" description="Astro Tag List Example for Blog">
<h2><i class="fas fa-tag"></i> {tagname} - {tagcount} {tagcount>1 ? 'posts' : 'post'}</h2>
{tagged.map(post => (
<a href={post.url}>
<div class="xpost-item box">
<img src={post.frontmatter.og.basic.image} height="140" class="float-start me-3" />
<h4>{post.frontmatter.title}</h4>
<p>{post.frontmatter.summary}</p>
{post.frontmatter.tags.map(tag => (
<a href={`/blog/tag-post/${tag}`}><span class="badge bg-secondary me-1 mb-2">{tag}</span></a>
))}
</div>
</a>
))}
</BaseLayout>
<style is:inline>
.xpost-item { border:1px solid #000; padding: 0 15px 0 0; margin:10px 0; border-radius:10px; overflow:auto; }
a { text-decoration:none; }
.xpost-item:hover { border:1px solid #f72; }
</style>
I included /*commentary*/
through-out the code.