RSS feed generation library for Astro projects with comprehensive configuration options and TypeScript support
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Zod-based validation schemas for TypeScript integration and content collection validation, ensuring RSS feed items meet requirements and providing runtime type checking.
Zod schema for validating RSS feed items, used internally and available for content collection integration.
/**
* Zod schema for RSS feed item validation
* Used for content collections and runtime validation
* Includes automatic date transformation and URL validation
*/
const rssSchema: ZodObject<{
title: ZodOptional<ZodString>;
description: ZodOptional<ZodString>;
pubDate: ZodOptional<ZodEffects<ZodUnion<[ZodString, ZodNumber, ZodDate]>, Date, string | number | Date>>;
customData: ZodOptional<ZodString>;
categories: ZodOptional<ZodArray<ZodString>>;
author: ZodOptional<ZodString>;
commentsUrl: ZodOptional<ZodString>;
source: ZodOptional<ZodObject<{
url: ZodString; // Must be valid URL
title: ZodString;
}>>;
enclosure: ZodOptional<ZodObject<{
url: ZodString;
length: ZodNumber; // Must be non-negative integer
type: ZodString;
}>>;
link: ZodOptional<ZodString>;
content: ZodOptional<ZodString>;
}>;Schema Features:
pubDate accepts string, number, or Date and transforms to Date objectsource.url validates URL formatenclosure.length validates non-negative integersUse rssSchema to validate content collection entries for RSS feed compatibility.
Basic Schema Usage:
// src/content/config.ts
import { defineCollection } from "astro:content";
import { rssSchema } from "@astrojs/rss";
const blog = defineCollection({
schema: rssSchema,
});
export const collections = { blog };Extended Schema Usage:
// src/content/config.ts
import { defineCollection, z } from "astro:content";
import { rssSchema } from "@astrojs/rss";
const blog = defineCollection({
schema: rssSchema.extend({
// Add custom fields while maintaining RSS compatibility
draft: z.boolean().default(false),
featured: z.boolean().default(false),
coverImage: z.string().optional(),
readingTime: z.number().optional(),
tags: z.array(z.string()).optional(),
}),
});
export const collections = { blog };The schema validates the following RSS feed item fields:
interface RSSSchemaFields {
/** Optional string for item title */
title?: string;
/** Optional string for item description */
description?: string;
/**
* Optional publication date
* Accepts string, number, or Date - automatically converted to Date
* Validates that the resulting Date is valid (not NaN)
*/
pubDate?: string | number | Date;
/** Optional string containing valid XML */
customData?: string;
/** Optional array of category strings */
categories?: string[];
/** Optional author email address string */
author?: string;
/** Optional comments URL string */
commentsUrl?: string;
/** Optional source object for republished content */
source?: {
/** Required source URL (must be valid URL) */
url: string;
/** Required source title */
title: string;
};
/** Optional media enclosure for podcasts/videos */
enclosure?: {
/** Required media URL */
url: string;
/** Required file size (non-negative integer) */
length: number;
/** Required MIME type string */
type: string;
};
/** Optional link URL string */
link?: string;
/** Optional full content HTML string */
content?: string;
}The schema enforces several important validation rules:
title or description must be providedpubDate accepts multiple formats but converts to Date objectsource.url must be a valid URL formatenclosure.length must be a non-negative integerValid Blog Post:
---
title: "Building RSS Feeds with Astro"
description: "Learn how to create RSS feeds in your Astro project"
pubDate: 2023-06-01
categories: ["astro", "rss", "tutorial"]
author: "developer@example.com"
---
Content here...Valid Podcast Episode:
---
title: "Episode 5: Web Performance"
description: "Discussion about modern web performance techniques"
pubDate: "2023-06-15T10:00:00Z"
categories: ["podcast", "performance"]
author: "host@podcast.com"
enclosure:
url: "https://example.com/episode5.mp3"
length: 25600000
type: "audio/mpeg"
customData: '<itunes:duration>42:30</itunes:duration>'
---
Episode show notes...Republished Content:
---
title: "Interesting Article from External Source"
description: "Summary of an interesting article we're sharing"
pubDate: 2023-06-20
source:
title: "Tech News Daily"
url: "https://technews.example.com/feed.xml"
categories: ["news", "external"]
---
Our commentary on this external article...The schema provides detailed error messages for validation failures:
// Example validation errors:
// Missing required fields
// Error: "At least title or description must be provided."
// Invalid date
// Error: "pubDate should be string, not undefined."
// Invalid URL
// Error: "source.url should be string, not number."
// Invalid enclosure length
// Error: "enclosure.length should be number, not string."// src/content/config.ts
import { defineCollection, z } from "astro:content";
import { rssSchema } from "@astrojs/rss";
const blog = defineCollection({
schema: rssSchema
.extend({
// Add custom fields
slug: z.string(),
readingTime: z.number(),
// Transform categories to tags for RSS compatibility
tags: z.array(z.string()).optional(),
})
.transform((data) => ({
...data,
// Map tags to categories for RSS schema compatibility
categories: data.tags || data.categories,
})),
});The schema provides full TypeScript type inference:
import type { z } from "astro:content";
import { rssSchema } from "@astrojs/rss";
// Infer the TypeScript type from the schema
type RSSFeedItem = z.infer<typeof rssSchema>;
// Use in your functions
function processRSSItem(item: RSSFeedItem) {
// Full type safety and autocompletion
console.log(item.title); // string | undefined
console.log(item.pubDate); // Date | undefined
console.log(item.categories); // string[] | undefined
}