RSS ke 66 rangkaian sosial: Facebook, Instagram, X, LinkedIn, Telegram dan banyak lagi Blog Afiliasi Hubungi Kami
Log masuk Mula percuma
Updated: 2026-10-15
Deno Fresh RSS Feed: Build a Route and Auto-Post New Posts

Short answer: A Deno Fresh RSS feed is one route file. Create routes/rss.xml.ts, export a GET handler that loads the newest published posts, builds RSS 2.0 XML with escaped text and absolute links, and returns a standard Response with the content type application/rss+xml. Add a short Cache-Control header, validate the output once and paste the address into an auto-poster, so that every new post is shared on social media automatically.

Fresh is a web framework for Deno that renders pages on the server and sends very little JavaScript to the browser. It uses file-based routing, so a route is simply a file in the routes folder. That makes a feed easy: a route does not have to render a page, it can return any response. This guide shows the route, a data source based on Deno KV, caching, the differences between Fresh versions and the mistakes that most often break feeds. At the end you will see how to share each item automatically.

Why a feed is just a route in Fresh

An RSS document is plain XML served over HTTP. In Fresh, a route file can export a handler for each HTTP method, and the handler returns a standard Web Response. There is nothing to install and no template to write. The only decisions are where the posts come from and how to turn them into XML. The data can live in Deno KV, a SQL database, Markdown files or an upstream API. If your content sits in a system without a native feed, the idea is the same as in auto-posting from a headless CMS without native RSS: build the feed yourself and let the auto-poster read it.

The route file

This example is written for Fresh 1.x, the file-based version. Save it as routes/rss.xml.ts. Posts are stored in Deno KV under keys that start with ["posts", publishedAt, id], where publishedAt is an ISO date string, so that the keys sort by date:

import { Handlers } from "$fresh/server.ts";

const SITE = "https://www.example.com";

interface Post {
  id: string;
  slug: string;
  title: string;
  summary: string;
  image?: string;
  publishedAt: string;
  status: string;
}

const esc = (value: string | undefined) => (value ?? "")
  .replace(/&/g, "&")
  .replace(/</g, "&lt;")
  .replace(/>/g, "&gt;");

export const handler: Handlers = {
  async GET() {
    const kv = await Deno.openKv();
    const posts: Post[] = [];
    for await (const entry of kv.list<Post>({ prefix: ["posts"] }, { reverse: true, limit: 40 })) {
      if (entry.value.status === "published") posts.push(entry.value);
      if (posts.length === 20) break;
    }

    const items = posts.map((post) => {
      const link = SITE + "/blog/" + post.slug;
      const image = post.image ? new URL(post.image, SITE).href : "";
      return "<item>"
        + "<title>" + esc(post.title) + "</title>"
        + "<link>" + esc(link) + "</link>"
        + '<guid isPermaLink="false">post-' + post.id + "</guid>"
        + "<pubDate>" + new Date(post.publishedAt).toUTCString() + "</pubDate>"
        + "<description>" + esc(post.summary) + "</description>"
        + (image ? '<enclosure url="' + esc(image) + '" type="image/jpeg" length="0"/>' : "")
        + "</item>";
    });

    const xml = '<?xml version="1.0" encoding="UTF-8"?>'
      + '<rss version="2.0"><channel>'
      + "<title>Example Blog</title>"
      + "<link>" + SITE + "/blog</link>"
      + "<description>News and articles from Example</description>"
      + items.join("")
      + "</channel></rss>";

    return new Response(xml, {
      headers: {
        "Content-Type": "application/rss+xml; charset=utf-8",
        "Cache-Control": "public, max-age=300",
      },
    });
  },
};

The feed is available at /rss.xml as soon as the application runs. The dots in the file name are allowed, so the route keeps the familiar address. If you do not use Deno KV, replace the loop with your own data access; everything below it stays the same.

Fresh 2 and other versions

Fresh has been changing its routing API between major versions. In the file-based version above, a route exports a handler object. In newer versions the application is built with an app object, and a route is registered with a call such as app.get("/rss.xml", handler), where the handler receives a context and returns a Response. The logic inside does not change: load the posts, build the XML and return a Response with the right headers. Check the documentation of the version you run, and copy only the part that builds the XML.

Why each line matters

The helper esc converts ampersands and angle brackets into entities. Without it, a title such as “Tips & tricks” produces invalid XML, and many readers and auto-posters stop at the first error. If your summaries contain HTML, escape them or wrap them in CDATA; the rules are in CDATA and HTML in RSS descriptions.

The loop reads the newest keys first and stops at 20 published posts. A feed does not need your whole archive, and a short feed is fetched faster. Keys sorted by the publication date also prevent an edited old post from jumping to the top. The GUID uses the post ID. If you used the slug and later renamed a post, an auto-poster could share it twice; see why your RSS feed auto-posts the same article twice. Dates use toUTCString(), which produces the RFC 822 format that RSS expects, as described in RSS date formats and pubDate errors.

Markdown files instead of a database

Many Fresh sites keep posts as Markdown files with front matter. In that case, read the folder with Deno.readDir, parse the front matter of each file, drop the drafts, sort by date and take the newest twenty. Reading and parsing files on every request is wasteful, so keep the result in memory for a few minutes, or build a small index when the site is deployed. The date should come from the front matter, not from the file system, because a deployment can change the modification time of every file at once and make the whole archive look new. Always exclude drafts and files with a future date.

Absolute links and images

Items are read outside your website, so every address must be complete. A relative link such as /blog/my-post or an image path such as /img/cover.jpg works in a browser on your site but fails in a reader or on a social network. The call new URL(path, SITE) turns a relative image path into an absolute one and keeps addresses that are already absolute. This class of mistake is described in relative URLs in RSS feeds. Choose images about 1200 pixels wide; sizes for each network are listed in social media image sizes.

Caching the feed

Feeds are requested constantly by readers, crawlers and auto-posters, while the data changes rarely. The header in the example lets browsers, proxies and the edge network reuse the response for five minutes. You can add a second layer by keeping the generated XML in a variable inside the module and refreshing it when it is older than a few minutes. On a platform with several instances, each instance keeps its own copy, which is fine for a feed. Keep the lifetime short: a feed cached for a day delays every share by a day, which defeats the purpose of automation.

One feed per category

Fresh supports dynamic routes, so a file such as routes/category/[name]/rss.xml.ts can serve a feed for every category. Read the value from the route parameters, check it against a list you control and filter the posts before building the XML. Reuse the same builder function by moving it into a shared module. Separate feeds let you send news to one channel, tutorials to another and announcements to a team chat, instead of publishing everything everywhere. The idea is explained in category filtering for auto-posting.

Deploying on Deno Deploy or your own server

Fresh sites are often hosted on Deno Deploy, but the feed works the same on any host that runs Deno. Two details deserve attention. First, Deno KV on a hosted platform is a shared database, while a local KV file used during development is separate, so a feed that works on your machine can be empty in production until you add data there. Second, the permissions of the runtime must allow the access your code needs, such as reading files or environment variables, if you use them. After every deployment, request the production address and confirm that the newest post is present. A short check takes seconds, and it catches the empty-feed problem before an auto-poster reports it. Keep the route in version control with the rest of the site, so that the address survives redesigns and migrations.

Common mistakes to avoid

  • Returning the XML with the default type. A string response may be sent as text. Always set application/rss+xml; see the Content-Type guide.
  • Whitespace before the XML declaration. The declaration must be the first characters of the document; see fixing the XML declaration error.
  • Using file dates for posts. A redeploy can change them all. Use a date stored with the post.
  • Publishing drafts by accident. Filter on the status in code, before building the XML.
  • Using a preview address. Preview deployments change and may require a login. Use the production domain.
  • Changing the GUID later. A new GUID makes an old post look new and can trigger a repeat share.

Test the feed before connecting it

  1. Request the feed with curl -i and check that the status is 200 and the content type is application/rss+xml. The method is described in debugging an RSS feed with curl.
  2. Confirm that the newest post is first and that no draft appears.
  3. Open several item links and image addresses; they must use your public https domain.
  4. Run the feed through the W3C Feed Validation Service.
  5. Request the feed from the deployed address, not only from your local machine.

The framework is documented at fresh.deno.dev.

How PostRSS works with a Fresh site

PostRSS has been publishing RSS and Atom feeds to social networks since 2014. Paste the address of your rss.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 post, 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, hashtags from categories and posting windows let you tune each channel, and the REST API 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.

Bacaan Berkaitan

The bottom line

A Deno Fresh RSS feed is a single route file that returns XML. Load the newest published posts, escape every text value, use a stable ID for the GUID, make links and images absolute and return a Response with the content type application/rss+xml and a short cache lifetime. Check which Fresh version you run, validate the feed once and test it on the deployed domain. After that, every post you publish can reach your social channels automatically.

FAQ

Does Fresh have a built-in RSS feed generator?

No. Fresh is a general web framework. You add the feed as a normal route that builds RSS XML from your posts and returns it with the correct content type.

Can a file name contain dots, such as rss.xml.ts?

Yes. The route file keeps the address that readers expect, and the handler inside returns the XML as a standard response.

Do I need Deno KV for the feed?

No. Deno KV is only one data source. You can read Markdown files, a SQL database or an API, as long as you produce a list of published posts with a title, a link, a date and a summary.

Why does my feed show the wrong dates?

The date probably comes from the file system or from a time zone conversion. Store the publication date with the post, and convert it with the toUTCString method.

Can I use the Fresh feed with PostRSS?

Yes. Paste the public feed address as a source in PostRSS, connect your social accounts and each new item is posted automatically. Make sure the address opens without a login first.

{“@context”: “https://schema.org”, “@type”: “FAQPage”, “mainEntity”: [{“@type”: “Question”, “name”: “Does Fresh have a built-in RSS feed generator?”, “acceptedAnswer”: {“@type”: “Answer”, “text”: “No. Fresh is a general web framework. You add the feed as a normal route that builds RSS XML from your posts and returns it with the correct content type.”}}, {“@type”: “Question”, “name”: “Can a file name contain dots, such as rss.xml.ts?”, “acceptedAnswer”: {“@type”: “Answer”, “text”: “Yes. The route file keeps the address that readers expect, and the handler inside returns the XML as a standard response.”}}, {“@type”: “Question”, “name”: “Do I need Deno KV for the feed?”, “acceptedAnswer”: {“@type”: “Answer”, “text”: “No. Deno KV is only one data source. You can read Markdown files, a SQL database or an API, as long as you produce a list of published posts with a title, a link, a date and a summary.”}}, {“@type”: “Question”, “name”: “Why does my feed show the wrong dates?”, “acceptedAnswer”: {“@type”: “Answer”, “text”: “The date probably comes from the file system or from a time zone conversion. Store the publication date with the post, and convert it with the toUTCString method.”}}, {“@type”: “Question”, “name”: “Can I use the Fresh feed with PostRSS?”, “acceptedAnswer”: {“@type”: “Answer”, “text”: “Yes. Paste the public feed address as a source in PostRSS, connect your social accounts and each new item is posted automatically. Make sure the address opens without a login first.”}}]}

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.

Lebih banyak alat daripada pasukan kami

Dibina oleh Internet Solutions, pasukan di sebalik PostRSS. Setiap produk menjimatkan masa anda dengan cara tersendiri.