#Content Collections and Next/Previous?

22 messages · Page 1 of 1 (latest)

dense wasp
#

How would this be updated for content collections?

import { Article } from '../domain/types';

export type Props = {
    readonly currentArticle: Article;
};
const { currentArticle } = Astro.props;

const allArticles =
    (await Astro.glob<Article>('../pages/posts/**/*.mdx'))
    .map((article) => ({
        ...article.frontmatter,
        url: article.url,
        title: apaStyleCasing(article.frontmatter.title),
        dates: { published: new Date(article.frontmatter.dates.published as unknown as string) } 
    }));

const sortedArticles = sortArticlesByDate(allArticles);
const currentArticleIndex = sortedArticles.findIndex((article) => article.url === currentArticle.url);
const previousArticle = sortedArticles[currentArticleIndex + 1];
const nextArticle = sortedArticles[currentArticleIndex - 1];
#

It's currently used <ArticlePreviousNext currentArticle={ article } /> inside my Article.astro

#

Could I just get the list of articles from the content collections api in place of Astro.glob?

#

or is there a better way

dense wasp
#

Hellooooooo

hoary sun
#

Sorry, I missed this, but I should have the solution. This getStaticPaths method is from a template repo I've been working on. Basically we just map the collection passing the next and previous entries to the page as props. I then pass these to my layout as props themselves. I've adapted it here to provide everything you should need.

export async function getStaticPaths() {
  const docs = await getCollection('blog');
  return docs.map(/* sort function */).map((entry, i) => ({
    params: { id: entry.slug },
    props: { entry, nextEntry: docs[i - 1], prevEntry: docs[i + 1], index: i },
  }));
}

interface Props {
  entry: CollectionEntry<'blog'>;
  nextEntry?: CollectionEntry<'blog'>;
  prevEntry?: CollectionEntry<'blog'>;
  index: number;
}

const { entry, nextEntry, prevEntry, index } = Astro.props;
const { Content } = await entry.render();

Let me know if there's anything else I missed, or if something doesn't work

dense wasp
#

thanks - so it looks like its almost drop in for astro.glob then, docs I mean

#

So in this case, rather than ArticlePreviousNext .astro using content collections, you chose to have it passed in as props? that makes sense

#

either way would work though right, it could still happen in ArticlePreviousNext ?

hoary sun
#

yeah

hoary sun
dense wasp
#

Interesting thanks - haven't migrated to content collections yet but wanted to run this part by someone as it seems the most complex part

#

What do you think is better then, make an explicit prev next part, or have a component that is told what the current article is and then uses content collections api to load prev and next info?

hoary sun
#

I'd say getting the prev/next articles from that first getCollection call is probably best, because you're only performing that iteration once + all the data you need is already there anyway

dense wasp
#

yes thats a good point

dense wasp
#

@hoary sun can you spot whats wrong here? im not able to override the title

#
export const articleSchema = z.object({
    url: z.string().optional(),
    title: z.string(),
    description: z.string().optional(),
    categories: z.array(z.string()),
    dates: datesSchema,
    images: imagesSchema.optional(),
    related: relatedSchema.optional(),
    status: statusSchema.optional(),
    featured: z.boolean().optional(),
    hideFromRss: z.boolean().optional(),
});
export type Article = Readonly<z.infer<typeof articleSchema> & {
    previous: Article | undefined;
    next: Article | undefined;
}>;
#

the types

#

It's because it needs to be inside data isnt it? hmm

dense wasp
#
    const mapped = articles.map((entry, index) => ({
        params: { slug: entry.slug },
        props: { entry: { ...entry, data: { ...entry.data, title: apStyleTitleCase(entry.data.title) }, previous: articles[index - 1], next: articles[index + 1] } }
    }));