Skip to content

Commit f5ed3c5

Browse files
committed
feat: add RSS and Atom feed generation for blog posts
- Implemented `generateFeed` function to create RSS and Atom feeds. - Added routes for `.NET` specific feeds in both RSS and Atom formats. - Created general feed routes for all posts in both RSS and Atom formats.
1 parent 79b2730 commit f5ed3c5

8 files changed

Lines changed: 493 additions & 65 deletions

File tree

nuxt.config.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,9 @@ export default defineNuxtConfig({
7777
// Optional: Add route rules for full prerendering
7878
routeRules: {
7979
'/**': { prerender: true },
80-
'/gitcheatsheet': { redirect: '/goodies/gitcheatsheet', prerender: true }
80+
'/gitcheatsheet': { redirect: '/goodies/gitcheatsheet', prerender: true },
81+
'/*.rss': { prerender: true },
82+
'/*.atom': { prerender: true }
8183
},
8284

8385
eslint: {

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,12 @@
2424
"@unhead/vue": "^2.0.19",
2525
"@vueuse/nuxt": "^13.9.0",
2626
"better-sqlite3": "^12.4.6",
27+
"feed": "^5.1.0",
2728
"just-kebab-case": "^4.2.0",
2829
"nuxt": "^4.2.2",
2930
"posthog-js": "^1.310.1",
3031
"submitjson": "^0.13.0",
32+
"ufo": "^1.6.1",
3133
"zod": "^4.1.13"
3234
},
3335
"devDependencies": {

pnpm-lock.yaml

Lines changed: 420 additions & 64 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

server/feed.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { joinURL } from 'ufo'
2+
import { Feed } from 'feed'
3+
import { queryCollection } from '@nuxt/content/server'
4+
import type { EventHandlerRequest, H3Event } from 'h3'
5+
6+
export async function generateFeed(event: H3Event<EventHandlerRequest>, tags: string[] = []): Promise<Feed> {
7+
const baseUrl = 'https://techwatching.dev'
8+
const siteUrl = joinURL(baseUrl, 'posts')
9+
const feed = new Feed({
10+
title: 'Alexandre Nedelec\'s blog',
11+
description: 'Alexandre Nédélec\'s blog',
12+
id: siteUrl,
13+
link: siteUrl,
14+
language: 'en',
15+
favicon: joinURL(baseUrl, 'favicon.ico'),
16+
copyright: `Copyright © 2019-${new Date().getFullYear()} Alexandre Nedelec All Rights Reserved`,
17+
feedLinks: {
18+
rss: `${baseUrl}/feed.rss`,
19+
atom: `${baseUrl}/feed.atom`
20+
}
21+
})
22+
23+
const articles = await queryCollection(event, 'posts')
24+
.order('date', 'DESC')
25+
.all()
26+
27+
for (const article of articles.filter(article => tags.length === 0 || article.tags?.some((tag: string) => tags.includes(tag)))) {
28+
feed.addItem({
29+
link: joinURL(baseUrl, article.path ?? ''),
30+
image: joinURL(baseUrl, article.image?.src ?? ''),
31+
title: article.title!,
32+
date: new Date(article.date),
33+
description: article.description,
34+
author: article.authors?.map(a => ({ name: a.name, link: a.to })),
35+
category: article.tags?.map(tag => ({ name: tag }))
36+
})
37+
}
38+
39+
return feed
40+
}

server/routes/dotnet_feed.atom.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { generateFeed } from '~~/server/feed'
2+
3+
export default defineEventHandler(async (event) => {
4+
const feed = await generateFeed(event, ['.NET'])
5+
appendHeader(event, 'Content-Type', 'application/xml')
6+
return feed.atom1()
7+
})

server/routes/dotnet_feed.rss.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { generateFeed } from '~~/server/feed'
2+
3+
export default defineEventHandler(async (event) => {
4+
const feed = await generateFeed(event, ['.NET'])
5+
appendHeader(event, 'Content-Type', 'application/xml')
6+
return feed.rss2()
7+
})

server/routes/feed.atom.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { generateFeed } from '~~/server/feed'
2+
3+
export default defineEventHandler(async (event) => {
4+
const feed = await generateFeed(event)
5+
appendHeader(event, 'Content-Type', 'application/xml')
6+
return feed.atom1()
7+
})

server/routes/feed.rss.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { generateFeed } from '~~/server/feed'
2+
3+
export default defineEventHandler(async (event) => {
4+
const feed = await generateFeed(event)
5+
appendHeader(event, 'Content-Type', 'application/xml')
6+
return feed.rss2()
7+
})

0 commit comments

Comments
 (0)