Getting Post List in Astro + Starlight
When building documentation or blog websites with Astro + Starlight, retrieving and displaying post lists is a common requirement. This article will explain in detail how to implement this functionality.
Using the getCollection API
Astro provides a powerful content collection API that makes it easy to retrieve post lists. Here’s the basic usage:
---import { getCollection } from 'astro:content';
// Get all blog postsconst posts = await getCollection('docs');---
Post Filtering and Sorting
You can use JavaScript array methods to filter and sort posts:
---import { getCollection } from 'astro:content';
// Get all posts and sort by dateconst posts = await getCollection('docs', ({ data }) => { return data.draft !== true; // Exclude draft posts}).then(posts => posts.sort((a, b) => new Date(b.data.date).getTime() - new Date(a.data.date).getTime() ));---
Categorizing by Tags
If you want to categorize posts by tags, you can do it like this:
---import { getCollection } from 'astro:content';
// Get all postsconst allPosts = await getCollection('docs');
// Create tag mappingconst tagToPosts = {};allPosts.forEach(post => { post.data.tags?.forEach(tag => { if (!tagToPosts[tag]) { tagToPosts[tag] = []; } tagToPosts[tag].push(post); });});---
Displaying Post Lists in Pages
After retrieving the post list, you can display them in your pages:
---// Post retrieval code above...---
<ul> {posts.map(post => ( <li> <a href={`/docs/${post.slug}`}> <h2>{post.data.title}</h2> <p>{post.data.excerpt}</p> <time datetime={post.data.date.toISOString()}> {post.data.date.toLocaleDateString()} </time> </a> </li> ))}</ul>
Pagination Functionality
If you have many posts, you might need to add pagination:
---import { getCollection } from 'astro:content';
// Pagination configurationconst postsPerPage = 10;const currentPage = Astro.url.searchParams.get('page') || 1;
// Get all postsconst allPosts = await getCollection('docs');const totalPages = Math.ceil(allPosts.length / postsPerPage);
// Get posts for current pageconst posts = allPosts.slice( (currentPage - 1) * postsPerPage, currentPage * postsPerPage);---
{/* Post list display code */}
<!-- Pagination navigation --><nav> {currentPage > 1 && ( <a href={`?page=${currentPage - 1}`}>Previous</a> )}
{currentPage < totalPages && ( <a href={`?page=${currentPage + 1}`}>Next</a> )}</nav>
Custom Sorting and Filtering
You can customize post sorting and filtering rules according to your needs:
---import { getCollection } from 'astro:content';
// Sort by custom rulesconst posts = await getCollection('docs', ({ data }) => { // Only get posts with specific tags return data.tags?.includes('featured');}).then(posts => // Sort by reading time posts.sort((a, b) => (b.data.readingTime || 0) - (a.data.readingTime || 0) ));---
Important Considerations
-
Performance Optimization: When dealing with a large number of posts, consider implementing pagination or virtual scrolling.
-
Type Safety: If using TypeScript, you can define types for your post collections:
interface BlogSchema { title: string; date: Date; excerpt?: string; tags?: string[]; draft?: boolean;}
const posts = (await getCollection('docs')) as CollectionEntry<BlogSchema>[];
- Caching Considerations: Results from getCollection are automatically cached by Astro, so you don’t need to worry about performance.
Conclusion
Astro + Starlight provides powerful and flexible APIs for handling post lists. By properly using these APIs, you can easily implement post retrieval, filtering, sorting, and display functionality. Based on your specific requirements, you can further optimize and extend these features to create a better user experience.