RSS į 66 socialinius tinklus: Facebook, Instagram, X, LinkedIn, Telegram ir kitus Blogas Partnerių programa Kontaktai
Prisijungti Pradėti nemokamai
Updated: 2026-10-06
Express RSS Feed in Node.js: Generate It and Auto-Post Posts

Short answer: An Express RSS feed in Node.js is one route. Install the feed package, load your latest published posts, add each one with an absolute link, a stable ID and a real Date, then send feed.rss2() with the application/rss+xml content type and a short cache. Validate it once and any RSS auto-poster can share every new article automatically.

Express is still the most common way to run a Node.js website or API, and plenty of blogs, documentation sites, product changelogs and news sections are served by a hand-built Express app. Because Express is minimal by design, nothing gives you a feed automatically. That matters more than it seems: a feed is how readers subscribe, how newsletters and aggregators find your latest content, and how social automation tools publish each new post the moment it goes live. This guide shows a reliable way to build the feed, the details that most often break Node feeds, and how to connect the result to social auto-posting.

What an Express RSS feed has to deliver

Start from the requirements. A dependable feed:

  • lists the most recent public items, newest first, usually 20 to 50 of them;
  • gives each item a title, an absolute link, a summary, a publication date and a permanent unique ID;
  • describes the channel with a title, a link to the site and a description;
  • is served as RSS or XML in UTF-8, with no redirects;
  • stays stable, so tools never treat an old item as new.

Images and categories are optional, but they shape how social posts look, so we add them once the basic feed validates.

Step 1: choose a feed library

Two npm packages cover almost every Express project:

  • feed produces RSS 2.0, Atom 1.0 and JSON Feed from one object. It is a good default when you want several formats from the same data. Its usage is documented in the feed package repository.
  • rss is a smaller package focused on RSS 2.0 only, with a simple item() call per post and xml() to output the document.

Both escape titles and summaries and format dates correctly, which removes the main reasons hand-written template feeds fail. The examples below use feed:

npm install feed

Step 2: the feed route

The example assumes a data function getPublishedPosts(limit) that returns posts with title, slug, summary ir publishedAt, newest first, and only those whose publication time has passed. The public base URL comes from an environment variable, which is the most predictable way to get correct absolute links.

const express = require('express');
const { Feed } = require('feed');

const app = express();
const BASE_URL = (process.env.BASE_URL || 'https://example.com').replace(//$/, '');

app.get('/rss.xml', async (req, res, next) => {
  try {
    const posts = await getPublishedPosts(30);

    const feed = new Feed({
      title: 'Example Blog',
      description: 'New articles from Example',
      id: BASE_URL + '/',
      link: BASE_URL + '/',
      language: 'en',
      copyright: 'Example',
      updated: posts[0] ? new Date(posts[0].publishedAt) : new Date(),
      feedLinks: { rss: BASE_URL + '/rss.xml' }
    });

    for (const p of posts) {
      const url = `${BASE_URL}/blog/${p.slug}`;
      feed.addItem({
        title: p.title,
        id: url,
        link: url,
        description: p.summary,
        date: new Date(p.publishedAt)
      });
    }

    res.set('Cache-Control', 'public, max-age=300');
    res.type('application/rss+xml; charset=utf-8').send(feed.rss2());
  } catch (err) {
    next(err);
  }
});

A few lines deserve attention. The item id is the permanent article URL, which becomes the item’s guid and should never change after publication. The channel updated date follows the newest post instead of the current time, so the feed does not look changed on every request. Errors are passed to next(), so a failed database query produces a proper error response rather than a half-written XML document that tools may misread.

Dates, encoding and HTML in summaries

Three details cause most Node feed problems.

  • Real Date objects. Pass a JavaScript Date, not a formatted string. The library outputs the RFC 822 style date RSS expects. If your database returns timestamps without a time zone, make sure they are interpreted as UTC, otherwise every item shifts by the server’s offset.
  • UTF-8 throughout. Node strings are Unicode, and Express sends UTF-8 when the content type says so. Problems usually come from the database connection or from content pasted from word processors with invisible control characters, which are invalid in XML.
  • HTML summaries. If summary contains HTML, decide whether to strip it to plain text or keep it. Plain text produces cleaner social posts; full HTML belongs in the item’s content field, which the library places in content:encoded.

Our article on content:encoded versus description explains which field usually becomes the social caption, and the guide to RSS date format errors covers date problems in detail.

Absolute URLs and trust proxy

The example uses a configured BASE_URL. If you build links from the request instead, with req.protocol ir req.get('host'), be careful behind Nginx, a load balancer or a platform router: Express then sees the internal connection, typically plain HTTP.

  • Enable trust proxy. app.set('trust proxy', 1) tells Express to read X-Forwarded-Proto from one proxy hop, so req.protocol becomes https. Only trust as many hops as you actually have. The Express guide to running behind proxies lists the accepted values.
  • Prefer configuration for feeds. A fixed base URL also works in build scripts and static exports, where there is no request.
  • Check the live output. Search the public feed for http://, localhost, :3000 and internal host names.

Relative links are the other half of the problem: they work in your templates but break once an item is read elsewhere, as explained in our guide to relative URLs and broken links in RSS feeds.

Images, categories and discovery

Richer items produce better social posts. After the basic feed validates, add:

  • An image per item. The image field of addItem accepts an absolute URL, which the library writes as an enclosure. Use a mid-sized picture; many auto-posting tools take it as the post image.
  • Categories. The category field takes an array of objects with a name. Tools can turn categories into hashtags or filter items by topic.
  • Open Graph tags. Give every article page og:title, og:description ir og:image; tools often fall back to them.
  • Autodiscovery. In the layout of your template engine, add <link rel="alternate" type="application/rss+xml" title="Example Blog" href="https://example.com/rss.xml"> so browsers and tools can find the feed.

Atom, JSON Feed and category feeds

Because one Feed object can be serialised in several formats, extra formats are nearly free. Move the building code into a function such as buildFeed(posts, title), then add /atom.xml returning feed.atom1() with application/atom+xml, and /feed.json returning feed.json1() if you want JSON Feed. Most auto-posting tools read RSS or Atom.

The same function serves category feeds. Add a route such as /category/:slug/rss.xml, look up the category, return 404 when it does not exist, and pass the filtered posts with a category-specific title. Keep each article’s ID identical in every feed. If duplicates still appear in social channels, the guide on duplicate GUID fixes explains how auto-posters decide what is new.

Caching, ETags and 304 responses

Feeds are polled constantly by readers, aggregators and auto-posting services, often every few minutes. Without caching, every request queries the database and rebuilds the XML.

  • Cache-Control. A public max-age of a few minutes, as in the example, lets a reverse proxy or CDN serve most requests.
  • Built-in ETags. Express adds a weak ETag to responses sent with res.send() by default, and answers 304 Not Modified when the client’s If-None-Match matches. Well-behaved clients then download the full feed only when it changed.
  • In-memory cache. Store the generated XML with a timestamp and rebuild it only when it is older than a few minutes or when a post is published. On several instances, use a shared cache such as Redis instead.
  • Small payload. Thirty items with summaries is enough for subscribers and automation.

Long cache lifetimes delay auto-posting, so keep them short. Our explanation of why cached feeds make auto-posts lag shows how the delays add up.

Test and troubleshoot

A short test with supertest protects the feed. Request /rss.xml, expect status 200 and a content type containing application/rss+xml, then parse the body with an XML parser and check that the first item has a title, an absolute link and a pubDate. Run it in CI so a refactor that breaks the route is caught before release.

ProblemTypical cause in ExpressFix
Links use http or port 3000trust proxy not setConfigured BASE_URL or app.set(‘trust proxy’)
Feed shown as plain textDefault text/html or text/plain typeres.type(‘application/rss+xml; charset=utf-8’)
Dates shifted by hoursTimestamps without a time zoneStore and parse timestamps as UTC
Half-written XML on errorsExceptions inside an async routeCatch and pass errors to next()
Same post shared twiceItem ID built from an editable titleUse the permanent URL as the ID
Feed always looks changedChannel date set to new Date()Use the newest post’s date

Before connecting automation, fetch the headers with curl -I, expect HTTP 200 without redirects, validate the feed and open a few item links in a private window to confirm they are public.

Connect the feed to social auto-posting

With a valid feed in place, sharing no longer depends on someone remembering to post. Add the feed URL to an auto-posting service, connect your social accounts and channels, decide how posts are built from the title, summary and link, and choose posting hours if you need them. The service checks the feed and publishes each new item once.

JavaScript teams often route content by audience: product news to a professional network, engineering posts to Mastodon or Bluesky, changelog entries to a Discord server, a Telegram channel or a team chat. Category feeds make every route a matter of picking the right feed. More setups are collected under technical guides and the RSS kanalas topic.

How PostRSS works with an Express feed

PostRSS reads any RSS or Atom feed, including one served by an Express route, and publishes each new item to the networks you connect. It checks feeds as often as every minute, takes the image from the feed item or the page’s Open Graph tags, and offers keyword filters, hashtags from item categories and UTM parameters. Developers can also use the PostRSS REST API v1 and outgoing webhooks, and the service has been running since 2014. See the features page for all 66 networks and the pricing page for what each plan includes.

Related reading

The bottom line

An Express RSS feed in Node.js takes one route and a few careful choices: a feed library for safe XML, a configured HTTPS base URL, real UTC dates, permanent item IDs, the right content type, proper error handling and a short cache. Add images and categories, offer Atom from the same object if you like, cover the route with a supertest check and validate it once. From then on the feed runs quietly, and every new article reaches subscribers and your social channels without manual sharing.

FAQ

Does Express have built-in RSS support?

No. Express is a minimal framework, so a feed is a normal route that returns XML. Packages such as feed or rss build the document for you.

Should I use the feed or the rss package?

Use feed when you want RSS, Atom and JSON Feed from one object. The rss package is a lighter choice when you only need RSS 2.0.

Why do my feed links start with http instead of https?

Behind a proxy Express sees the internal HTTP connection. Use a configured base URL, or enable trust proxy so req.protocol reflects the original scheme.

Does Express handle ETags for my feed?

Yes. By default Express adds a weak ETag to bodies sent with res.send and returns 304 Not Modified when the client already has the current version.

Can I auto-post new Express blog posts to social media?

Yes. Once the feed is public and valid, an RSS auto-posting service can watch it and publish each new post to the social networks and channels you connect.

New guides, once a month

What changed in the networks, what broke, and how to fix it before it costs you reach.

We send a confirmation e-mail first. Unsubscribe any time.

Daugiau mūsų komandos įrankių

Sukūrė Internet Solutions – PostRSS komanda. Kiekvienas produktas sutaupo laiko savaip.

PostRSS – RSS srautų automatizavimas ir autoskelbimo įrankis
Privatumo apžvalga

Ši svetainė naudoja slapukus, kad galėtume užtikrinti geriausią įmanomą vartotojo patirtį. Slapukų informacija yra saugoma jūsų naršyklėje ir atlieka tokias funkcijas, kaip jūsų atpažinimas grįžus į mūsų svetainę bei mūsų komandai padeda suprasti, kurios svetainės skiltys jums yra įdomiausios ir naudingiausios.