
Short answer: Strapi has no built-in RSS feed, because it is a headless CMS that serves content through an API rather than web pages. You add a Strapi RSS feed in one of two places: in your front end, which fetches published entries from the Strapi API and renders RSS XML, or inside Strapi itself, with a custom route and controller that return the feed. Either way, link each item to the public page on your website, use absolute image URLs and a stable date and GUID, and then connect the feed to an auto-poster so every newly published entry is shared on social media.
Strapi is one of the most widely used open-source headless CMS platforms. Editors manage articles in the admin panel, and a separate website or app built with Next.js, Nuxt, Astro, SvelteKit or something else displays them. That split is the reason there is no feed by default: Strapi does not know your website’s URLs or templates. This guide shows both ways to build the feed, with code for Strapi 5 and notes for Strapi 4, and explains the details that decide whether automation tools can use it: links, dates, images, drafts, locales and caching.
A traditional CMS such as WordPress renders pages and knows the address of every post, so it can publish a feed at a fixed URL. Strapi only stores structured content and exposes it as JSON through REST and GraphQL. The page for an article might live at https://example.com/blog/my-post, at a path with a locale prefix, or in a mobile app with no URL at all. Strapi cannot guess.
That means you define three things yourself:
The general problem is described in auto-posting from a headless CMS without native RSS. The rest of this guide is the Strapi-specific answer.
A feed is only as good as the fields behind it. For an Article collection type, make sure you have:
The dedicated date field deserves a word. Strapi sets publishedAt automatically, and that works for many sites. But depending on version and workflow, publishing an edited entry again can update that timestamp, which can push an old article to the top of the feed and make automation tools treat it as new. An editor-controlled date field avoids the problem: sort the feed by it and fall back to publishedAt only when it is empty.
If your website is server-rendered or statically generated, the front end is the natural place for the feed, because it already knows its own URLs. The pattern is the same in every framework: a route such as /rss.xml fetches the latest published articles from Strapi and returns XML.
The REST request for Strapi 5 looks like this:
GET /api/articles?sort=publishedAt:desc
&pagination[pageSize]=20
&fields[0]=title&fields[1]=slug
&fields[2]=summary&fields[3]=publishedAt
&populate[0]=coverIn Strapi 5 each entry comes back with its fields at the top level and a documentId. In Strapi 4 the fields sit inside an attributes object and the numeric id identifies the entry, so adjust the mapping if you are on the older version. In both, the REST API returns published content by default when Draft and Publish is on.
A front-end route in Node-style JavaScript, using the popular feed package from npm, could look like this:
import { Feed } from 'feed';
const SITE = 'https://example.com';
const CMS = process.env.STRAPI_URL;
export async function GET() {
const res = await fetch(CMS + '/api/articles?sort=publishedAt:desc'
+ '&pagination[pageSize]=20&populate[0]=cover', {
headers: { Authorization: 'Bearer ' + process.env.STRAPI_TOKEN },
});
const { data } = await res.json();
const feed = new Feed({
title: 'Example Blog',
description: 'News and articles from Example',
id: SITE + '/blog/',
link: SITE + '/blog/',
copyright: 'Example',
});
for (const a of data) {
const url = SITE + '/blog/' + a.slug;
const img = a.cover ? new URL(a.cover.url, CMS).href : undefined;
feed.addItem({
title: a.title,
id: url,
link: url,
description: a.summary,
date: new Date(a.date || a.publishedAt),
image: img,
});
}
return new Response(feed.rss2(), {
headers: { 'Content-Type': 'application/rss+xml; charset=utf-8' },
});
}This shape fits route handlers in Next.js, SvelteKit, Astro and similar frameworks. Framework-specific details, such as static export and revalidation, are covered in adding an RSS feed to a Next.js site および Nuxt RSS feeds.
If several front ends share one Strapi instance, or your site is a single-page app with no server, it can be simpler to let Strapi produce the feed. Create an API folder with a route and a controller. The route file, src/api/feed/routes/feed.js:
module.exports = {
routes: [
{
method: 'GET',
path: '/feed.xml',
handler: 'feed.index',
config: { auth: false },
},
],
};The controller, src/api/feed/controllers/feed.js, using Strapi 5’s Document Service:
const { Feed } = require('feed');
const SITE = process.env.PUBLIC_SITE_URL;
const CMS = process.env.PUBLIC_CMS_URL;
module.exports = {
async index(ctx) {
const posts = await strapi.documents('api::article.article').findMany({
status: 'published',
sort: 'publishedAt:desc',
limit: 20,
populate: ['cover'],
});
const feed = new Feed({ title: 'Example Blog', id: SITE, link: SITE,
description: 'News and articles from Example', copyright: 'Example' });
for (const p of posts) {
const url = SITE + '/blog/' + p.slug;
feed.addItem({ title: p.title, id: url, link: url,
description: p.summary, date: new Date(p.date || p.publishedAt),
image: p.cover ? new URL(p.cover.url, CMS).href : undefined });
}
ctx.set('Cache-Control', 'public, max-age=300');
ctx.type = 'application/rss+xml; charset=utf-8';
ctx.body = feed.rss2();
},
};Strapi prefixes content API routes with /api, so the feed is available at https://cms.example.com/api/feed.xml. auth: false makes this one route public without opening the rest of your API. On Strapi 4, use strapi.entityService.findMany with a filter on publishedAt instead of the Document Service. PUBLIC_SITE_URL is your website and PUBLIC_CMS_URL the public address of the Strapi server, which hosts locally uploaded images. Restart Strapi after adding the files.
Whichever version you use, the base URL for links must be your public website, not the Strapi server. A feed whose links open the CMS host is the most common mistake with this option.
Feed readers and automation tools read each item out of context, so every URL must be absolute and must point to a page people can open.
/uploads/cover_1a2b3c.jpg, served from the Strapi host. Prefix them with the Strapi public URL, as the code above does. Cloud upload providers usually return absolute URLs already.Rich text needs care too. Strapi 5’s Blocks editor stores content as structured JSON, and the older Markdown rich text field stores Markdown. Neither is HTML, so you would need a renderer to put the full body into the feed. For automation, the plain summary field is simpler and better: it is short, already clean and exactly what you want in the first line of a social post. Background on this choice is in full-text vs excerpt RSS feeds.
Finally, make sure each article page on your website outputs Open Graph tags, especially og:image, because many networks build the preview card from the page rather than the feed. Image selection is explained in how to control which image gets auto-posted.
With Draft and Publish on, only published entries should ever reach the feed. Both options above request published content explicitly or by default, but test it: create a draft with an obvious title and confirm it does not appear.
For Option 1, the front end needs permission to read articles. You can either allow the find action for the Article type on the Public role under Users and Permissions, or create a read-only API token in the admin settings and send it from the server as in the example. A token is the safer choice when the API is not meant to be public, and it must stay on the server, never in browser code.
| Question | Front-end feed | Strapi custom route |
|---|---|---|
| Knows public URLs | Yes, natively | Needs a site URL setting |
| Works with a static site | Yes, generated at build | Yes, served live |
| Freshness | Depends on rebuild or cache | Immediate after publish |
| Several front ends | One feed per front end | One shared feed |
| Feed address | On your website domain | On the CMS domain |
A feed generated on a static site only changes when the site rebuilds. Strapi webhooks, configured under Settings and Webhooks, can call your hosting provider’s deploy hook on the entry.publish event so the site, and with it the feed, rebuilds after each publication. The same event can purge a CDN cache if the feed is served dynamically.
Keep cache times on the feed short in any case, a few minutes at most. A feed that is cached for a day delays every social post by up to a day. How automation tools notice new items, and why polling a feed is still the most robust method, is explained in RSS vs webhooks vs API polling.
With the Internationalization feature, each locale is a separate version of the same document. Request one locale at a time with the locale parameter, for example locale=de, and publish one feed per language, such as /rss.xml および /de/rss.xml. Connect each feed to the social accounts that speak that language.
The GUID, called id in the feed package, must never change for a published item. The page URL works well if slugs are not edited after publication. If they might be, use the Strapi identifier instead, combined with the locale when you have several, for example https://example.com/articles/abc123-en. In Strapi 5, all locales of a document share the same documentId, which is why the locale belongs in the GUID. Duplicate posts caused by changing GUIDs are explained in why a feed auto-posts the same article twice.
Before any tool starts reading the feed, check it as an outsider would:
application/rss+xml and the status 200; debugging an RSS feed with curl shows how.Strapi’s routes, controllers, Document Service and webhooks are documented in the Strapi documentation; check the pages for your major version, as Strapi 4 and 5 differ in places.
PostRSS has been publishing RSS and Atom feeds to social networks since 2014. Paste the address of your Strapi feed, from your website or from the custom route, connect your accounts and choose how each post is built from the title, the description or the page title. PostRSS checks the feed as often as every minute and shares each new article, with its image and link, to the channels you choose among 66 supported networks, messengers, team chats and blogs, from LinkedIn and Bluesky to Telegram, Discord and DEV. Keyword filters, UTM parameters, hashtags from categories and posting windows let you tune every channel, and the REST API and webhooks are there if you want to connect your own systems. See the PostRSS features page and the plan limits on the pricing page. More developer guides are under the Technical Guide tag.
Strapi stores content but does not publish feeds, so you add a Strapi RSS feed yourself: in the front end, which knows its URLs, or with a small custom route in Strapi. Use a summary field for descriptions, a stable date and GUID, absolute links to your public site and absolute image URLs. Keep drafts out, keep the cache short, rebuild static sites with a publish webhook and validate the result. Then every article you publish in Strapi can reach your social channels automatically.
No. Strapi is a headless CMS that serves content as JSON through REST and GraphQL. You create the feed in your front end or with a custom route and controller in Strapi.
Content API routes are prefixed with /api, so a route with the path /feed.xml is served at /api/feed.xml on your Strapi server. Set auth to false in the route config to make it public.
The local upload provider returns relative URLs such as /uploads/file.jpg. Prefix them with the public URL of your Strapi server, or use a cloud upload provider that returns absolute URLs.
Enable Draft and Publish on the content type and request only published entries. The REST API returns published content by default, and the Document Service accepts a published status filter.
Always to your public website. Build each item link from your site base URL and the article slug, because readers and social networks need the page people actually visit.
What changed in the networks, what broke, and how to fix it before it costs you reach.
PostRSSを手がけるInternet Solutionsが開発。どの製品も、それぞれの形で時間を節約します。