RSS para 66 redes sociais: Facebook, Instagram, X, LinkedIn, Telegram e mais Blog Afiliado Contatos
Entrar Começar grátis
Updated: 2026-10-25
SolidStart RSS Feed: API Route, Dates and Auto-Posting

Short answer: To add an RSS feed to a SolidStart site, create an API route file named feed.xml.ts in the routes folder that exports a GET function, load your published posts on the server, build the document with the rss package so every value is escaped, and return a Response with the application/rss+xml content type. Use the publication date of each post, take the last build date from the newest post, add an ETag so repeat requests end in a 304, test the route with curl and a validator, and give the public address to an auto-poster so new posts are shared automatically.

SolidStart is the meta-framework for Solid, and it is popular for fast blogs, documentation sites, portfolios and small shops that want server rendering without the weight of larger tools. A site like that publishes something readers want to follow, and the standard way to let them do it, without an account or an API key, is an RSS feed. SolidStart has no feed module, but it has something that serves the purpose better: file-based API routes that return ordinary web Response objects. This guide builds a complete feed route with stable identifiers, correct dates, conditional requests and static generation as an alternative, explains each decision and ends with the checks that keep the feed dependable once other systems rely on it.

When a SolidStart site needs a feed

A feed is worth adding to every site that publishes on a schedule: a blog, a changelog, a newsletter archive, an events page or a catalogue of new products. Readers who follow it in a feed reader get every item in order. Search engines and aggregators discover new pages faster. And an auto-poster such as PostRSS can share each new post on social networks the moment it is published, which turns a quiet publishing routine into a steady stream of visitors.

Many frameworks have solved this in their own way; compare the SvelteKit RSS feed guide e the Astro RSS feed guide. If your content lives in a hosted blog or a CMS that already publishes a feed, use that one; see how to find your WordPress feed link.

Set up the project

Create a SolidStart project and add the rss package and its type definitions. The package builds a valid RSS 2.0 document from plain objects and escapes every value.

npm create solid@latest my-site
cd my-site
npm install
npm install rss
npm install -D @types/rss

Assume a module at src/lib/posts.ts that exports a function getPublishedPosts. It returns the posts, newest first, as objects with the fields slug, title, summary, imageUrl, imageBytes, imageType and publishedAt, where publishedAt is a Date. It may read Markdown files at build time, query a database or call a CMS; the feed code does not care. What matters is that it only returns posts whose publication time has already passed, because a post scheduled for tomorrow must not appear in the feed today.

The feed route

In SolidStart, a file in the routes folder that exports functions named after HTTP methods becomes an API route. A file called feed.xml.ts answers at the address /feed.xml. The code below builds the document, hashes it and answers conditional requests.

import type { APIEvent } from '@solidjs/start/server';
import RSS from 'rss';
import { createHash } from 'node:crypto';
import { getPublishedPosts } from '~/lib/posts';

const SITE = process.env.SITE_URL ?? 'https://example.com';

function etagMatches(header: string | null, etag: string): boolean {
  if (!header) return false;
  return header
    .split(',')
    .map((token) => token.trim().replace('W/', ''))
    .some((token) => token === '*' || token === etag);
}

export async function GET(event: APIEvent) {
  const posts = (await getPublishedPosts()).slice(0, 20);
  const newest = posts.length ? posts[0].publishedAt : new Date(0);

  const feed = new RSS({
    title: 'Example Journal',
    description: 'News and guides from Example Journal.',
    feed_url: `${SITE}/feed.xml`,
    site_url: `${SITE}/`,
    language: 'en',
    pubDate: newest,
  });

  for (const post of posts) {
    const url = `${SITE}/blog/${post.slug}/`;
    feed.item({
      title: post.title,
      description: post.summary,
      url,
      guid: url,
      date: post.publishedAt,
      enclosure: post.imageUrl
        ? { url: post.imageUrl, size: post.imageBytes ?? 0, type: post.imageType ?? 'image/jpeg' }
        : undefined,
    });
  }

  const body = feed.xml();
  const etag = '"' + createHash('sha256').update(body).digest('hex').slice(0, 32) + '"';
  const headers = {
    ETag: etag,
    'Cache-Control': 'public, max-age=300',
  };

  if (etagMatches(event.request.headers.get('if-none-match'), etag)) {
    return new Response(null, { status: 304, headers });
  }
  return new Response(body, {
    headers: { ...headers, 'Content-Type': 'application/rss+xml; charset=utf-8' },
  });
}

Start the development server with npm run dev and open /feed.xml. The tilde alias in the import points at the src folder in the default template; adjust it if your project uses a different alias. The rss package writes dates in the correct RFC 822 format from Date objects, in UTC.

Where to run it: server or build time

SolidStart can deploy to a Node server, to edge runtimes and to static hosting. The route above uses the node crypto module and the rss package, which suits a Node preset. On an edge runtime without Node modules, replace the hash with the Web Crypto API, for example crypto.subtle.digest, and check that the package works there. If your site is fully static, you can prerender the route, so the feed is written to a file at build time; list it among the routes that the prerender step should visit. A prerendered feed is fastest, but it only changes when you rebuild, so connect your publishing workflow to a rebuild, or the feed will lag behind the site.

How the ETag logic works

Auto-posters, readers and search engines request a feed often, and almost always nothing has changed. A validator lets them ask a cheap question: has the document changed since the version I hold? The route hashes the finished text, quotes the hash as an entity tag and compares it with the If-None-Match header. A match produces a 304 response with no body, which saves bandwidth for both sides.

The hash is computed from the body, which brings one rule: the body must not change unless the content changes. That is why the channel date comes from the newest post and not from the clock. If you wrote the current time into the document, the hash would change on every request, no client would ever receive a 304 and the validator would be useless. The same rule applies to any value generated at request time. A compressing proxy may turn a strong tag into a weak one with a W/ prefix, which is why the comparison removes it.

Where each field comes from

Feed elementSourceRule
titlePost titlePlain text, escaped by the package
linkPublic address of the pageAbsolute, with https, returning 200 directly
guidSame address, or a stored identifierNever changes after publication
pubDatePublication date of the postThe stored date, never the current time
descriptionShort summaryOne or two sentences of plain text
enclosureFeatured imageAddress, size in bytes and media type

The identifier is the most important decision. An auto-poster remembers which items it has already shared by their GUID. If the value changes when someone edits a slug or republishes a post, the same story is shared again. If slugs may change, store a permanent identifier and use it as the guid with the permalink flag turned off.

Make the feed discoverable

Readers and tools find a feed through a link in the head of every page. In SolidStart, add it in the root component or in the document head, using a link element with the type application/rss+xml and the address of the route. Browsers, feed readers and many auto-posting tools then detect the feed from any page of the site. A visible link on the blog page, near the subscribe buttons, helps people too. Keep one canonical feed address and redirect old addresses to it, so that anyone who subscribed earlier keeps receiving new posts.

Caching without delaying new posts

The Cache-Control header in the example lets shared caches keep the response for five minutes, and the ETag lets everyone revalidate cheaply after that. If you place a content delivery network in front of the site, keep the lifetime short so a new post does not wait long for its turn. A feed that lags behind the website by an hour defeats the purpose of automation. For the background, read how auto-posting tools use ETags and conditional requests e what 301, 304, 404 and 500 mean for auto-posting.

Test the feed before you connect it

A few minutes of testing prevents days of confusion later. A small unit test can call the route function directly, because it only needs a request object.

import { describe, expect, it } from 'vitest';
import { GET } from '~/routes/feed.xml';

function call(headers: Record<string, string> = {}) {
  const request = new Request('http://localhost/feed.xml', { headers });
  return GET({ request } as never);
}

describe('feed route', () => {
  it('serves RSS and answers 304 for a matching ETag', async () => {
    const first = await call();
    expect(first.status).toBe(200);
    expect(first.headers.get('content-type')).toContain('application/rss+xml');
    const etag = first.headers.get('etag') as string;
    const second = await call({ 'if-none-match': etag });
    expect(second.status).toBe(304);
  });
});

Then check the running site from the outside:

  • Run curl -i https://example.com/feed.xml and confirm a 200 status, the right content type and an ETag header.
  • Repeat the request with the tag you received in an If-None-Match header and confirm that the answer is 304.
  • Paste the public address into the W3C Feed Validation Service and fix every error.
  • Publish a test post, wait for the cache lifetime and confirm that it appears once, at the top.

There is a longer checklist in the feed validation guide and a short curl routine in the guide to debugging a feed with curl.

Common mistakes to avoid

  • Current time in the body. It changes the hash on every request and disables the 304 answer.
  • Unstable GUIDs. Changing them makes auto-posters share old stories again; see why a feed auto-posts the same article twice.
  • Future posts in the feed. Always filter on the publication time.
  • Wrong content type. A feed sent as text or HTML confuses some readers; see the content type header guide.
  • A stale prerendered file. If you generate the feed at build time, rebuild whenever you publish.
  • Relative links. Every address in the feed must be absolute, because readers do not know your domain.

How PostRSS works with a SolidStart feed

PostRSS has been publishing RSS and Atom feeds to social networks since 2014. Paste the address of your feed 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.

Leitura relacionada

The bottom line

SolidStart needs only an API route file and a small library to serve a dependable RSS feed: load published posts dated in the past, let the library escape every value, use a stable GUID, take the channel date from the newest post and send the result with the right content type. Add a hash-based ETag so repeat requests end in a 304, link the feed from every page, test with curl and a validator, keep the address unchanged and connect it to an auto-poster. After that, every post you publish can reach your social channels automatically.

FAQ

Does SolidStart have a built-in RSS generator?

No. SolidStart has no feed support, but a file-based API route such as feed.xml.ts can return the output of a library like rss with the application/rss+xml content type.

Can I generate the feed at build time?

Yes. If your site is static, prerender the route so the feed is written as a file. Just remember to rebuild whenever you publish, or the feed will lag behind the website.

Why does my feed never return 304?

Most often the body changes between requests, for example because the channel date is the current time. Take that date from the newest post and the hash stays the same until the content changes.

How many items should the feed contain?

Between ten and twenty of the newest published posts is enough. An auto-poster only needs recent items, and a smaller file is faster to download and parse.

Can I use this feed with PostRSS?

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.

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.

Mais ferramentas da nossa equipe

Criadas pela Internet Solutions, a equipe por trás do PostRSS. Cada uma economiza seu tempo de um jeito diferente.