Tag Filtering - agiusalexandre.com
Blog readers needed a way to browse content by topic instead of scrolling through all posts.
The Problem
Blog readers had no way to browse content by topic. Finding articles about a specific subject meant scrolling through all posts hoping to spot relevant titles. With a growing number of articles, this was becoming frustrating.
The Solution
Built a complete tag browsing system:
- Tags index page at
/tagsshowing all tags with post counts - Individual tag pages at
/tags/[tag-name]listing filtered posts - Clickable tags throughout the site with consistent color coding
How It Works
The tag index page builds a count map and sorts tags by popularity:
// Build tag count map
const tagCounts = new Map<string, number>();
posts.forEach(post => {
post.data.tags?.forEach(tag => {
tagCounts.set(tag, (tagCounts.get(tag) || 0) + 1);
});
});
// Sort tags by count (descending), then alphabetically
const sortedTags = Array.from(tagCounts.entries())
.sort((a, b) => {
if (b[1] !== a[1]) return b[1] - a[1];
return a[0].localeCompare(b[0]);
});
Dynamic tag pages use Astro’s getStaticPaths to generate routes at build time:
export async function getStaticPaths() {
const posts = await getCollection('blog', ({ data }) => !data.draft);
// Collect all unique tags
const tags = new Set<string>();
posts.forEach(post => {
post.data.tags?.forEach(tag => tags.add(tag));
});
// Create a path for each tag
return Array.from(tags).map(tag => ({
params: { tag: tag.toLowerCase().replace(/\s+/g, '-') },
props: {
originalTag: tag,
posts: posts.filter(post => post.data.tags?.includes(tag))
},
}));
}
Color-coded tags maintain visual consistency:
const tagColors: Record<string, string> = {
'AWS': 'bg-orange-100 text-orange-700 hover:bg-orange-200',
'AI': 'bg-purple-100 text-purple-700 hover:bg-purple-200',
'Security': 'bg-red-100 text-red-700 hover:bg-red-200',
'Development': 'bg-blue-100 text-blue-700 hover:bg-blue-200',
'default': 'bg-gray-100 text-gray-700 hover:bg-gray-200',
};
Key Files Changed
| File | Change |
|---|---|
src/pages/tags/index.astro | New tags index page with post counts |
src/pages/tags/[tag].astro | Dynamic tag filter pages |
src/components/PostCard.astro | Made tags clickable with color styling |
What I Learned
- Astro’s content collections make tag aggregation straightforward — The
getCollectionAPI provides easy access to all posts and their metadata - Static generation handles tags naturally — No runtime database queries needed, all tag pages are pre-built
- URL slugification matters — Converting “AI-DLC” to “ai-dlc” ensures clean, consistent URLs while preserving the original tag name for display
Do It Yourself
Key takeaways
- Static generation handles tags naturally — Astro’s
getStaticPathspre-builds all tag pages at compile time, eliminating the need for runtime database queries or client-side filtering logic. - URL slugification ensures consistency — Converting tags like “AI-DLC” to “ai-dlc” for URLs while preserving the original case for display prevents broken links and improves SEO.
- Visual consistency improves navigation — Color-coding tags by category (AWS = orange, AI = purple, Security = red) helps readers quickly scan and recognize content types across the site.
Try it now
-
Implement tag filtering in your Astro blog: Follow the Astro content collections tutorial and add tag pages using
getStaticPaths— the pattern applies to any metadata field. -
Add client-side tag filtering: Use Alpine.js or vanilla JavaScript to filter posts by tag without page navigation. Example: Alpine.js filtering pattern.
-
Enhance with tag clouds: Visualize tag popularity using the d3-cloud library or CSS-based tag cloud patterns to show relative tag frequencies at a glance.
ONE LETTER A MONTH · NO TRACKER · UNSUBSCRIBE ANYTIME
Comments
Sign in to leave a comment
