
Astro provides an extension called astro-rss that allows you to easily generate an RSS feed for your site.
In the documentation, that at the time of writing is available in the README of the github repository and in the Astro’s official documentation, there is no mention of how to add an image to the feed.
In this article I will show you 3 ways to add an image to your Astro RSS feed.
1. Use the RSS feed image tag
The simplest way to add an image to your RSS feed is to use the <image>
tag in the <item>
tag.
The <item>
tag is generated by the astro-rss
extension for every item you add to the feed but, if you try to add an
image: ...
field to the item definition, you will find out that it won’t work. It will just be ignored.
So, how can we add an image tag to our RSS feed? You can use customData.
We will see that customData
is used in more than one of the examples, but in this case it won’t need a xmlns
attribute
as indicated in the documentation.
Add these changes to the item definition to use the RSS image
tag:
import rss from '@astrojs/rss';
import { getCollection } from 'astro:content';
import { getImage } from 'astro:assets';
export async function GET(context) {
const blog = await getCollection('blog');
return rss({
title: 'My Blog',
description: 'My Blog Description',
site: context.site,
items: await Promise.all(blog.map(async (post) => {
const image = await getImage(post.data.image);
return {
title: post.data.title,
pubDate: post.data.pubDate,
description: post.data.description,
customData: `<image>
<url>${context.site.origin + image.src}</url>
<title>${post.data.title}</title>
<link>${context.site.origin + post.data.url}</link>
<width>${image.width}</width>
<height>${image.height}</height>
</image>`,
...
}
})),
});
}
You are not forced to getImage
to get the image metadata, you can use any other way you want.
This is just an example that shows a convenient way to get the image metadata, provided by Astro.
You can use the image
field (or any other name you have used) in the frontmatter of your posts to store the image metadata,
but getImage
ensure your image src is correctly processed by Astro.
Notice that getImage
is asynchronous, so you will need to await it, which in turns forces you to use an async
anonymous
function in blog.map
. The result of this operation is an array of promises, so you need to await them all with Promise.all
to get the final result.
This system works well, and it is relatively simple to use. Also, consider that you can add your image as base64 data, although this is not recommended.
I am not 100% sure if the image
field is broadly supported by all RSS readers, but I have tested it with a few and worked fine.
Just in case you might find some reader that doesn’t support it, you can always use one of the following alternatives. Also, these three methods are not exclusive, and you can combine any of them in your feed. You can use all of them together if you want.
2. Use the media tag defined in the RSS 2.0 specification
The second way to add an image to your RSS feed is to use the <media:content>
tag defined in the RSS 2.0 specification,
which was originally created by Yahoo! and is broadly supported by most RSS readers.
In this case, we will still use the customData
field, but we will add the xmlns:media
attribute to the root tag.
import rss from '@astrojs/rss';
import { getCollection } from 'astro:content';
import { getImage } from 'astro:assets';
export async function GET(context) {
const blog = await getCollection('blog');
return rss({
title: 'My Blog',
description: 'My Blog Description',
site: context.site,
xmlns: {
media: "http://search.yahoo.com/mrss/",
},
items: await Promise.all(blog.map(async (post) => {
const image = await getImage(post.data.image);
return {
title: post.data.title,
pubDate: post.data.pubDate,
description: post.data.description,
customData: `<media:content
type="image/${image.rawOptions.format}"
width="${image.width}"
height="${image.height}"
medium="image"
url="${context.site.origin + image.src}" />`,
...
}
})),
});
}
3. Use an enclosure
Enclosures are usually used to add audio or video content to your feed, but they can also be used to add images.
Most RSS readers support enclosures and will correctly display images in your feed added with this method.
The definition of the enclosure is supported through a field named enclosure
in the item definition. However, of the
three methods I have shown here, this is the least flexible and comes with the requirement of specifying the length
of the image in bytes.
Luckily, it is flexible enough to accept 0
in the length field, which will make the reader handle it for you.
import rss from '@astrojs/rss';
import { getCollection } from 'astro:content';
import { getImage } from 'astro:assets';
export async function GET(context) {
const blog = await getCollection('blog');
return rss({
title: 'My Blog',
description: 'My Blog Description',
site: context.site,
items: await Promise.all(blog.map(async (post) => {
const image = await getImage(post.data.image);
return {
title: post.data.title,
pubDate: post.data.pubDate,
description: post.data.description,
enclosure: {
url: image.src,
length: 0, //or the actual length if you have it
type: image.rawOptions.format,
},
...
}
})),
});
}
Conclusion
Remember that you can use any of these three methods to add an image to your RSS feed and that you can combine them to provide max compatibility with all readers.
I hope you have enjoyed this article and that you have learned something new.