
Short answer: To publish an RSS feed from Craft CMS, add a route for /feed.xml in config/routes.php, point it at a Twig template, query the newest live entries with craft.entries, write the RSS 2.0 XML in the template with the rss filter for dates, and send the content type application/rss+xml with a header tag. Craft escapes Twig output for you and only returns live entries by default. Test the feed with curl and a validator, and then give its public address to an auto-poster so every new entry reaches your social channels.
Craft CMS is a flexible content system that agencies and in-house teams use to build everything from magazines to product sites. Its templates are written in Twig, which means that a feed is not a plugin or a setting but one more template. That is a strength, because you decide exactly which entries, fields and images go into it. It is also why many Craft sites have no feed at all: nobody added the template. This guide builds a complete Craft CMS RSS feed, explains each decision and ends with the checks that keep it dependable.
A feed is worth adding whenever your site publishes things that people want to follow:
Without a feed, every new entry has to be copied to social networks by hand. For other content systems that need the same work, see the Statamic guide या the Strapi guide. If your content lives in a blog that already has a feed, use it; see how to find your WordPress feed link.
The example assumes a channel section with the handle news, with a plain text field called summary and, optionally, an assets field for a main image. Adapt the handles to your own project. First tell Craft that the address /feed.xml belongs to a template. Add it to the routes file:
<?php
// config/routes.php
return [
'feed.xml' => ['template' => 'feeds/news'],
];Craft also lets you define the same route in the control panel, but a file keeps it in version control. Keep the path unchanged after you connect it to a tool, because every change of address breaks the connection.
Create templates/feeds/news.twig. The header tags come first, and the whitespace control characters stop any blank line from appearing before the XML declaration, which would make the file invalid.
{%- header "Content-Type: application/rss+xml; charset=utf-8" -%}
{%- header "Cache-Control: public, max-age=300" -%}
{%- set posts = craft.entries()
.section('news')
.orderBy('postDate DESC')
.limit(20)
.all() -%}
{%- set newest = posts|first -%}
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>{{ siteName }}</title>
<link>{{ siteUrl }}news/</link>
<description>Latest news from {{ siteName }}</description>
<language>{{ currentSite.language|slice(0, 2) }}</language>
{% if newest %}<lastBuildDate>{{ newest.postDate|rss }}</lastBuildDate>{% endif %}
<atom:link href="{{ siteUrl }}feed.xml" rel="self" type="application/rss+xml"/>
{% for post in posts %}
<item>
<title>{{ post.title }}</title>
<link>{{ post.url }}</link>
<guid isPermaLink="false">craft-{{ post.id }}</guid>
<pubDate>{{ post.postDate|rss }}</pubDate>
<description>{{ post.summary }}</description>
</item>
{% endfor %}
</channel>
</rss>Several details carry most of the correctness. A Craft element query returns only live entries by default, which means enabled entries whose post date has passed and whose expiry date has not, so drafts and scheduled entries never appear. Twig escapes variables automatically, so an ampersand in a title becomes a safe entity and cannot break the file. The rss filter writes a date in the form that feeds expect. The GUID is built from the entry identifier and marked with isPermaLink set to false because it is an identifier and not an address. The limit keeps the file small.
| RSS element | Source in Craft | Rule |
|---|---|---|
| title | entry title | Escaped by Twig, under about 100 characters |
| link | entry URL | Always absolute and always the public address |
| guid | entry identifier | Never changes, even if the slug changes |
| pubDate | post date | RFC 822 style, never in the future |
| description | summary field | Plain text; the first sentences matter most |
The GUID deserves special attention. Use the entry identifier and not the slug, because slugs get edited. A new GUID makes an old item look new, and an auto-poster may share it again; see why your RSS feed auto-posts the same article twice. Date mistakes are another common cause of trouble; see RSS date format errors. If your summaries contain HTML, escape them as shown, or wrap them in CDATA as described in CDATA and HTML in RSS descriptions.
Auto-posters build the preview card from the image of the item, so add one when you can. If the section has an assets field, load the first image in the loop and write an enclosure element with its address, its size and its real type. The asset object exposes all three, so nothing has to be typed by hand. Use absolute addresses, because a relative one breaks when the feed is read elsewhere; see relative URLs in RSS feeds. The way these tags are handled is explained in RSS enclosure tags explained. Also make sure each entry page carries correct Open Graph tags, because many networks use them for the card.
A feed is requested often, mostly by robots. Each request here runs one small query, and the header in the template lets a proxy or a content delivery network serve the same copy for 300 seconds. Craft also offers a template cache tag, which stores the rendered result and clears it automatically when an entry used in it is saved, so a new entry appears without waiting for a timer. Do not cache for hours: a long lifetime delays every share by the same amount, as explained in RSS feed caching explained. Check the real response headers with curl after you deploy, because a server, a plugin or a content delivery network in front of Craft can add or replace a cache header.
Craft can serve several sites from one installation. Give each language its own feed address and its own route, and query the entries of that site only, so that one feed never mixes languages. The language element in the template reads the code from the current site, as in the example. Auto-posters treat each address as a separate source, which is what you want when each language has its own social accounts. Keep the feed paths consistent, for example the same file name under each site base address, so that they are easy to remember and to test.
The example sends a plain text summary, which is what an auto-poster needs for a caption. Some readers and tools also like the full article, and the content namespace of RSS lets you add it next to the summary. If you do, render the body to a string, keep it inside a CDATA block or escape it, and make sure it contains absolute links and image addresses. Sending the whole article makes the file larger, so lower the limit if you do. For auto-posting alone, a good summary of one or two sentences is usually better than the full text, because it becomes the caption and the link brings readers to your site, where they can see your design and your other pages. See full text versus excerpt feeds for the trade-offs.
A news section often contains more than one kind of entry, for example articles, events and press releases, and each kind may deserve its own feed. Craft makes this easy because the query can filter by entry type, by category or by a custom field. Create a template for each audience, give each its own route and keep the structure identical, so that only the query changes. That also lets an auto-poster send each feed to a different channel, for instance events to a local page and press releases to a business network. Routing by topic is explained in category filtering for auto-posting. Avoid putting every kind of entry into one large feed and filtering later, because the tool then has to guess which entries belong where.
curl -i https://www.example.com/feed.xml and check for a 200 status, the XML content type and the cache header. The method is explained in debugging an RSS feed with curl.If anything looks wrong later, the checklist in RSS feed not updating helps you find the cause quickly.
PostRSS has been publishing RSS and Atom feeds to social networks since 2014. Paste the address of your feed.xml 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 item, with its image and link, to the channels you choose among 66 supported networks, messengers, team chats and blogs, including LinkedIn, X, Bluesky, Mastodon and Telegram. Keyword filters, UTM parameters and posting windows let you tune each channel, and webhooks connect PostRSS to 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.
Craft CMS serves a dependable RSS feed with one route and one Twig template: query live entries from the right section, let Twig escape every value, use a stable GUID, write dates with the rss filter, use absolute links and send the XML with the right content type and a short cache. Keep the route unchanged, test with curl and a validator, and connect the address to an auto-poster. After that, every entry you publish can reach your social channels automatically.
No. Craft leaves the output to your templates, so a feed is a Twig template plus a route. That gives you full control over which entries and fields are included.
Element queries return live entries by default, meaning enabled entries whose post date has passed and which have not expired. That is exactly what a public feed should contain.
No. The template shown here works without a plugin. Some teams prefer a plugin for convenience, but a template is easy to read, easy to test and easy to keep in version control.
Between ten and twenty of the newest entries is enough. An auto-poster only needs recent items, and a smaller file is faster to download and parse.
Give every item a stable identifier and use it as the GUID. Avoid changing the post date of entries that are already public, because some tools treat a changed date as a new item.
Yes. PostRSS reads any valid RSS or Atom address that is reachable without a login. Paste the address, connect your channels and new items are shared as soon as they appear.
What changed in the networks, what broke, and how to fix it before it costs you reach.
PostRSS बनाने वाली टीम Internet Solutions की ओर से। हर प्रोडक्ट आपका समय अपने तरीके से बचाता है।