Closed eric-burel closed 1 week ago
RSS feed support is not something we are prioritizing right now. But we will accept a pull request for this, if proposed changes are not too complex.
I'll try to work on it later on. Related to PR #342, I would also like to be able to finetune meta tags for each lesson. This would require being able to pass an image URL through the lesson metadata, and it would be great to be able to do that in user-land without having to extend the framework.
Closing as this is now supported via PR #378
I've implemented a feed based on this, the trickiest part was to convert content ids into slugs based on the existing logic from getContent
, I've ended up with this quick and dirty implem (but working fine):
/**
* Dictionary of lesson id to actual slug
* Not super efficient but will be statically rendered anyway so don't bother
* { "1_patterns/2_chapter/3_lesson/content.mdx": "part-slug/chapter-slug/lesson-slug" }
* The key is "lesson.id" in the collection
* The value is the slug used as URL in the [...slug] page of tutorial kit
* @returns
*/
async function getSlugs() {
const chapters = await getCollection(
"tutorial",
({ data }) => data.type === "chapter"
);
const parts = await getCollection(
"tutorial",
({ data }) => data.type === "part"
);
const lessons = await getCollection(
"tutorial",
({ data }) => data.type === "lesson"
);
// p/1_foobar/2_baz/3_qux
// => we want to turn that into tutorial-slug/part-slug/chapter-slug/lesson-slug
let ids: Array<string> = lessons.map((l) => l.id);
const idsToSlugs = new Map<string, string>(ids.map((id) => [id, id]));
idsToSlugs.forEach((slug, id) => {
idsToSlugs.set(id, slug.replace("1-patterns", "p"));
// remove the dangling "/content.mdx"
idsToSlugs.set(id, slug.replace("/content.mdx", ""));
});
parts.forEach((pt) => {
// id is the actual filename, we want the slug
// 1_patterns/meta.md => 1_patterns
const partId = pt.id.split("/")[0];
idsToSlugs.forEach((slug, id) => {
// 3_part => part-3-slug
idsToSlugs.set(id, slug.replace(partId, pt.slug));
});
});
chapters.forEach((ch) => {
// 1_patterns/2_chapter/meta.md => 2_chapter
const chapterId = ch.id.split("/")[1];
idsToSlugs.forEach((slug, id, m) => {
// 2_chapter => chapter-2-slug
idsToSlugs.set(id, slug.replace(chapterId, ch.slug));
});
});
lessons.forEach((l) => {
// 1_patterns/2_chapter/meta.md => 2_chapter
const lessonId = l.id.split("/")[2];
idsToSlugs.forEach((slug, id, m) => {
// 2_chapter => chapter-2-slug
idsToSlugs.set(id, slug.replace(lessonId, l.slug));
});
});
return Object.fromEntries(idsToSlugs.entries());
}
Now you get a map of each "id" -> "URL". I'll post another issue on that specifically.
Is your feature request related to a problem?
Hi, Since I am "building in public" and crafting lessons as I go, I'd like to setup an RSS feed for some lessons.
In order to feed it, I would need to alter lessons metadata:
rss: true
field to lessons or parts I specifically want to be listed (to avoid generating a feed with everything)publishedAt
field to lessons to have a publication dateI would also need a way to get the lesson URL.
Describe the solution you'd like.
I'd like to either have an RSS feed out-of-the-box or be able to craft one in userland.
Describe alternatives you've considered.
Since RSS is a specific but common problematic, it could make sense to add the relevant to add the field I've listed into the contentSchema, to make it easy to implement a feed.
I would also need an helper to get a lessons link, which is the reverse operation from what
generateStaticRoutes
does to compute valid slugs. Perhaps we could precompute links when we build the "tutorial" collections?The other alternative is to allow passing a custom schema, so the frontmatter of lessons can be extended freely provided it keeps the tutorial kit mandatory fields around. I would still need a helper to get the lesson URL.
Additional context
I don't seem to have a typed result when I run
getCollection("tutorial")
, perhaps Astro system that types collections cannot cross packages?