The @vlozi/blog package ships two helpers for generating standard feeds. Both are pure functions — they fetch your posts and return a string of XML. Drop the result into a Route Handler.
RSS 2.0
import { generateRSS } from "@vlozi/blog";
import { vlozi } from "@/lib/vlozi";
// app/blog/rss.xml/route.ts
export async function GET() {
const xml = await generateRSS(vlozi, {
title: "My Blog",
description: "The latest from My Blog.",
siteUrl: "https://mysite.com",
feedUrl: "https://mysite.com/blog/rss.xml",
language: "en",
copyright: `© ${new Date().getFullYear()} My Company`,
maxPosts: 20,
});
return new Response(xml, {
headers: {
"Content-Type": "application/rss+xml; charset=utf-8",
"Cache-Control": "public, max-age=3600, s-maxage=3600",
},
});
}Options
| Option | Type | Default | Description |
|---|---|---|---|
title |
string | required | Feed title |
description |
string | required | Feed description |
siteUrl |
string | required | Root URL of your site (e.g. https://mysite.com) |
feedUrl |
string | required | URL of this feed itself (used for <atom:link>) |
language |
string | "en" |
Feed language code |
copyright |
string | — | Copyright notice included in the feed |
maxPosts |
number | 20 | Max posts to include; the most-recently-published posts are used |
postPath |
(post) => string |
/blog/{slug} |
Build the URL for each post |
The generated feed includes
<title>,<link>,<description>,<language>,<lastBuildDate><atom:link rel="self">for feed discovery- One
<item>per post:<title>,<link>,<description>(excerpt),<pubDate>,<guid>,<category>(if set)
Sitemap
import { generateSitemap } from "@vlozi/blog";
import { vlozi } from "@/lib/vlozi";
// app/blog/sitemap.xml/route.ts
export async function GET() {
const xml = await generateSitemap(vlozi, {
siteUrl: "https://mysite.com",
maxPosts: 1000,
});
return new Response(xml, {
headers: {
"Content-Type": "application/xml; charset=utf-8",
"Cache-Control": "public, max-age=86400, s-maxage=86400",
},
});
}Options
| Option | Type | Default | Description |
|---|---|---|---|
siteUrl |
string | required | Root URL of your site |
maxPosts |
number | 1000 | Max posts to include |
changefreq |
string | "weekly" |
<changefreq> value per entry |
priority |
number | 0.7 |
<priority> value per entry (0.0–1.0) |
postPath |
(post) => string |
/blog/{slug} |
Build the URL for each post |
The generated sitemap is standard <urlset> XML. Submit the URL to Google Search Console and Bing Webmaster Tools.
Wiring both into next-sitemap
If you use the next-sitemap package for your main sitemap, exclude /blog/* from it and let the Vlozi feed handle blog URLs:
// next-sitemap.config.js
module.exports = {
siteUrl: "https://mysite.com",
exclude: ["/blog/*"], // blog pages covered by /blog/sitemap.xml
additionalSitemaps: [
"https://mysite.com/blog/sitemap.xml",
],
};Announcing your feed
Link your RSS feed in the <head> for browsers and RSS readers to auto-discover it. In Next.js App Router, add it to your root layout metadata:
// app/layout.tsx
export const metadata = {
alternates: {
types: {
"application/rss+xml": [
{ url: "/blog/rss.xml", title: "My Blog RSS Feed" },
],
},
},
};TIP
An Atom 1.0 variant (generateAtom) is on the roadmap but not yet shipped. If you need Atom specifically, the RSS feed is accepted by every Atom-compatible reader — they support both formats.