#content collections
12 messages · Page 1 of 1 (latest)
Hi @alpine wigeon. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
Astro provides a powerful way to manage and author content using content collections. You can define a relationship, or "reference", from one collection to another using the reference() function.
To use the authors collection as a reference in the blog post schema, you can define a property in the blog post schema as an entry from the authors collection. Here's an example:
import { defineCollection, reference, z } from 'astro:content';
const blog = defineCollection({
type: 'content',
schema: z.object({
title: z.string(),
// Reference a single author from the `authors` collection by `id`
author: reference('authors'),
// Reference an array of related posts from the `blog` collection by `slug`
relatedPosts: z.array(reference('blog')),
})
});
const authors = defineCollection({
type: 'data',
schema: z.object({
name: z.string(),
portfolio: z.string().url(),
})
});
export const collections = { blog, authors };
In this example, every blog post entry includes an author property which uses the authors collection's own schema for type checking, autocomplete, and validation[^1^].
To display the author's name on each blog post static route, you can use the getEntry() function to query the author's data. Here's an example:
---
import { getEntry, getEntries } from 'astro:content';
const blogPost = await getEntry('blog', 'welcome');
// Resolve a singular reference
const author = await getEntry(blogPost.data.author);
// Resolve an array of references
const relatedPosts = await getEntries(blogPost.data.relatedPosts);
<h1>{blogPost.data.title}</h1>
<p>Author: {author.data.name}</p>
<!-- ... -->
<h2>You might also like:</h2>
{relatedPosts.map(p => ( <a href={p.slug}>{p.data.title}</a>))}
In this example, the `getEntry()` function is used to retrieve the author's data using the author's id from the blog post's data. The author's name is then displayed on the blog post page[^5^].
**^1^]: [Astro Documentation - Defining collection references** (<https://docs.astro.build/en/guides/content-collections#defining-collection-references>)
**^5^]: [Astro Documentation - Querying Collections** (<https://docs.astro.build/en/guides/content-collections#querying-collections>)
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
@alpine wigeon kapa.ai is still learning and improving, please let us know how it did by reacting below
@wide scarab how do I use this in my [..slug].astro file?
Let me check the knowledge base for you. One moment! :books:
To use the author's data in your [...slug].astro file, you would first need to import the getCollection and getEntry functions from 'astro:content'. Then, you can use the getStaticPaths function to generate the paths for each blog post and the getEntry function to fetch the author's data for each blog post.
Here's an example of how you can do this:
---
import { getCollection, getEntry } from 'astro:content';
import BlogPostLayout from '../../layouts/BlogPostLayout.astro';
export async function getStaticPaths() {
const blogEntries = await getCollection('posts');
return blogEntries.map(entry => ({ params: { slug: entry.slug }, props: { entry }, }));
}
const { entry } = Astro.props;
const { Content } = await entry.render();
const author = await getEntry('authors', entry.data.author);
---
<BlogPostLayout frontmatter={entry.data}>
<h2>Author: {author.data.name}</h2>
<Content />
</BlogPostLayout>
In this example, the getStaticPaths function is used to generate the paths for each blog post. The getEntry function is then used to fetch the author's data using the author's id from the blog post's data. The author's name is then displayed on the blog post page[^10^].
^10^]: [Astro Documentation - Generate pages from a collection (https://docs.astro.build/en/tutorials/add-content-collections#generate-pages-from-a-collection)
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@alpine wigeon kapa.ai is still learning and improving, please let us know how it did by reacting below
@wide scarab this throws the error "Cannot read properties of undefined (reading 'data')"
Let me check the knowledge base for you. One moment! :books:
The error message "Cannot read properties of undefined (reading 'data')" typically occurs when you're trying to access a property on an object that hasn't been defined yet. In this case, it seems like either entry or author might be undefined.
Here's a revised version of the code with checks to ensure entry and author are defined before trying to access their data properties:
---
import { getCollection, getEntry } from 'astro:content';
import BlogPostLayout from '../../layouts/BlogPostLayout.astro';
export async function getStaticPaths() {
const blogEntries = await getCollection('posts');
return blogEntries.map(entry => ({ params: { slug: entry.slug }, props: { entry }, }));
}
const { entry } = Astro.props;
const { Content } = entry ? await entry.render() : null;
const author = entry ? await getEntry('authors', entry.data.author) : null;
---
<BlogPostLayout frontmatter={entry?.data}>
<h2>Author: {author?.data.name}</h2>
<Content />
</BlogPostLayout>
In this revised code, we're using the optional chaining operator (?.) to access the data properties of entry and author. This operator returns undefined if the object before the ?. is undefined or null, preventing the error you're seeing.
Please note that this code assumes you have a BlogPostLayout.astro file in your layouts directory and that your authors' collection is named 'authors'. If that's not the case, you'll need to adjust the code accordingly.