From 80c20232f4981a1d6407537fc58a8c5cf5df24c9 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 23 Oct 2025 22:32:58 +0000
Subject: [PATCH 1/6] Initial plan
From 258923b7d7dd8a647401ce2a99b6fe39335d42fc Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 23 Oct 2025 22:46:13 +0000
Subject: [PATCH 2/6] Add RSS feed for recent rules updates
Co-authored-by: bradystroud <38869720+bradystroud@users.noreply.github.com>
---
_docs/RSS-Feed.md | 49 ++++++++++++++++++++++++++
gatsby-config.js | 87 +++++++++++++++++++++++++++++++++++++++++++++++
package.json | 1 +
yarn.lock | 52 ++++++++++++++++++++++++++++
4 files changed, 189 insertions(+)
create mode 100644 _docs/RSS-Feed.md
diff --git a/_docs/RSS-Feed.md b/_docs/RSS-Feed.md
new file mode 100644
index 000000000..f255f48d8
--- /dev/null
+++ b/_docs/RSS-Feed.md
@@ -0,0 +1,49 @@
+# RSS Feed
+
+SSW Rules provides an RSS feed for recent rules changes at `/rss.xml`.
+
+## Overview
+
+The RSS feed is generated during the build process using the `gatsby-plugin-feed` plugin. It provides:
+
+- The 50 most recently updated rules
+- Automatic filtering of archived rules
+- Information about who made the last update
+- Links to the updated rules
+- Rule descriptions from the SEO description or excerpt
+
+## Feed URL
+
+The RSS feed is available at:
+- Production: `https://www.ssw.com.au/rules/rss.xml`
+- Staging: Check the staging deployment URL and append `/rss.xml`
+
+## Usage
+
+Users can subscribe to this RSS feed using:
+- RSS readers (e.g., Feedly, Inoreader)
+- Email notifications via Power Automate or similar automation tools
+- Custom integrations
+
+## Configuration
+
+The RSS feed is configured in `gatsby-config.js` with the `gatsby-plugin-feed` plugin. The feed:
+
+1. Queries the `history.json` data for recent rule updates
+2. Sorts by `lastUpdated` date in descending order
+3. Filters out archived rules
+4. Limits to the 50 most recent updates
+5. Includes metadata such as title, description, author, and publication date
+
+## Technical Details
+
+The feed uses the following data sources:
+- `allHistoryJson`: Git history data sorted by last update date
+- `allMarkdownRemark`: Rule content including title, excerpt, and SEO description
+
+Each feed item includes:
+- **Title**: The rule title
+- **Description**: SEO description, excerpt, or update information
+- **Date**: Last update timestamp
+- **Author**: Last person who updated the rule
+- **URL**: Direct link to the rule
diff --git a/gatsby-config.js b/gatsby-config.js
index 624defe3b..5ac1361e2 100644
--- a/gatsby-config.js
+++ b/gatsby-config.js
@@ -37,6 +37,93 @@ module.exports = {
'gatsby-plugin-react-helmet',
'gatsby-plugin-sitemap',
'gatsby-transformer-json',
+ {
+ resolve: 'gatsby-plugin-feed',
+ options: {
+ query: `
+ {
+ site {
+ siteMetadata {
+ siteTitle
+ siteDescription
+ siteUrl
+ }
+ }
+ }
+ `,
+ feeds: [
+ {
+ serialize: ({
+ query: { site, allHistoryJson, allMarkdownRemark },
+ }) => {
+ // Create a lookup object for rules by file path
+ const rulesMap = {};
+ allMarkdownRemark.nodes.forEach((rule) => {
+ const filePath = `rules/${rule.frontmatter.uri}/rule.md`;
+ rulesMap[filePath] = rule;
+ });
+
+ // Get recent updates from history, filter out archived rules
+ return allHistoryJson.edges
+ .filter((edge) => {
+ const rule = rulesMap[edge.node.file];
+ return rule && !rule.frontmatter.archivedreason;
+ })
+ .slice(0, 50) // Limit to 50 most recent updates
+ .map((edge) => {
+ const rule = rulesMap[edge.node.file];
+ const url = `${site.siteMetadata.siteUrl}/${rule.frontmatter.uri}`;
+
+ return {
+ title: rule.frontmatter.title,
+ description:
+ rule.frontmatter.seoDescription ||
+ rule.excerpt ||
+ `Updated by ${edge.node.lastUpdatedBy}`,
+ date: edge.node.lastUpdated,
+ url: url,
+ guid: url,
+ custom_elements: [
+ { 'dc:creator': edge.node.lastUpdatedBy },
+ { pubDate: edge.node.lastUpdated },
+ ],
+ };
+ });
+ },
+ query: `
+ {
+ allHistoryJson(sort: {lastUpdated: DESC}) {
+ edges {
+ node {
+ file
+ lastUpdated
+ lastUpdatedBy
+ }
+ }
+ }
+ allMarkdownRemark(filter: {frontmatter: {type: {eq: "rule"}}}) {
+ nodes {
+ excerpt(pruneLength: 250)
+ frontmatter {
+ title
+ uri
+ archivedreason
+ seoDescription
+ }
+ }
+ }
+ }
+ `,
+ output: '/rss.xml',
+ title: 'SSW Rules - Recent Updates',
+ description: 'Stay updated with the latest changes to SSW Rules',
+ site_url: 'https://www.ssw.com.au/rules',
+ feed_url: 'https://www.ssw.com.au/rules/rss.xml',
+ language: 'en',
+ },
+ ],
+ },
+ },
'gatsby-plugin-postcss',
{
resolve: 'gatsby-source-git',
diff --git a/package.json b/package.json
index 1ac57da87..3e035330d 100644
--- a/package.json
+++ b/package.json
@@ -44,6 +44,7 @@
"gatsby-plugin-breadcrumb": "^12.3.2",
"gatsby-plugin-client-side-redirect": "^1.1.0",
"gatsby-plugin-decap-cms": "^4.0.4",
+ "gatsby-plugin-feed": "5.13.1",
"gatsby-plugin-fontawesome-css": "^1.2.0",
"gatsby-plugin-google-gtag": "^5.13.1",
"gatsby-plugin-google-tagmanager": "^5.13.1",
diff --git a/yarn.lock b/yarn.lock
index b657a7e04..f6dba724c 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6996,6 +6996,7 @@ __metadata:
gatsby-plugin-breadcrumb: "npm:^12.3.2"
gatsby-plugin-client-side-redirect: "npm:^1.1.0"
gatsby-plugin-decap-cms: "npm:^4.0.4"
+ gatsby-plugin-feed: "npm:5.13.1"
gatsby-plugin-fontawesome-css: "npm:^1.2.0"
gatsby-plugin-google-gtag: "npm:^5.13.1"
gatsby-plugin-google-tagmanager: "npm:^5.13.1"
@@ -13857,6 +13858,24 @@ __metadata:
languageName: node
linkType: hard
+"gatsby-plugin-feed@npm:5.13.1":
+ version: 5.13.1
+ resolution: "gatsby-plugin-feed@npm:5.13.1"
+ dependencies:
+ "@babel/runtime": "npm:^7.20.13"
+ common-tags: "npm:^1.8.2"
+ fs-extra: "npm:^11.1.1"
+ gatsby-plugin-utils: "npm:^4.13.1"
+ lodash.merge: "npm:^4.6.2"
+ rss: "npm:^1.2.2"
+ peerDependencies:
+ gatsby: ^5.0.0-next
+ react: ^18.0.0 || ^0.0.0
+ react-dom: ^18.0.0 || ^0.0.0
+ checksum: 35e88d70f26ebf8fc959f0e800ead7ed96ae2c77fc6499cba22656ac8252b073554a02024bb3c858d9f380fb70c70aa20341a9a8d7c13b101c22143e29900366
+ languageName: node
+ linkType: hard
+
"gatsby-plugin-fontawesome-css@npm:^1.2.0":
version: 1.2.0
resolution: "gatsby-plugin-fontawesome-css@npm:1.2.0"
@@ -18885,6 +18904,22 @@ __metadata:
languageName: node
linkType: hard
+"mime-db@npm:~1.25.0":
+ version: 1.25.0
+ resolution: "mime-db@npm:1.25.0"
+ checksum: a90951c80700314d6131e106cbf56ae94718d046e9669a5afd7f91e603248da328aad5b63314865fd9547f4688465ac62d1ace59e1ffdb73688452a28a9c3622
+ languageName: node
+ linkType: hard
+
+"mime-types@npm:2.1.13":
+ version: 2.1.13
+ resolution: "mime-types@npm:2.1.13"
+ dependencies:
+ mime-db: "npm:~1.25.0"
+ checksum: a53a0453f7863fa2d823025ce92978f5142a18528316caa53cbb1d4212be847973e9a5f2466362cbd2351a512e369252fc2c88c9c5bbc85df4bd8b42214f1785
+ languageName: node
+ linkType: hard
+
"mime-types@npm:^2.1.12, mime-types@npm:^2.1.27, mime-types@npm:^2.1.30, mime-types@npm:~2.1.19, mime-types@npm:~2.1.24, mime-types@npm:~2.1.34":
version: 2.1.35
resolution: "mime-types@npm:2.1.35"
@@ -23541,6 +23576,16 @@ __metadata:
languageName: node
linkType: hard
+"rss@npm:^1.2.2":
+ version: 1.2.2
+ resolution: "rss@npm:1.2.2"
+ dependencies:
+ mime-types: "npm:2.1.13"
+ xml: "npm:1.0.1"
+ checksum: 7e37a6ed1820b69476c76e4fefe09f69dd7505408e9fc7690441a5190aca2e2e2faf8d19575fd1efd66debfb178893374fbff9abf68e5416f5e4d4cccb7ae8b9
+ languageName: node
+ linkType: hard
+
"run-async@npm:^2.4.0":
version: 2.4.1
resolution: "run-async@npm:2.4.1"
@@ -27520,6 +27565,13 @@ __metadata:
languageName: node
linkType: hard
+"xml@npm:1.0.1":
+ version: 1.0.1
+ resolution: "xml@npm:1.0.1"
+ checksum: 04bcc9b8b5e7b49392072fbd9c6b0f0958bd8e8f8606fee460318e43991349a68cbc5384038d179ff15aef7d222285f69ca0f067f53d071084eb14c7fdb30411
+ languageName: node
+ linkType: hard
+
"xmlbuilder@npm:^15.1.1":
version: 15.1.1
resolution: "xmlbuilder@npm:15.1.1"
From 6334c1e2757b45d0e36fbd3ae9335e101ebb7c3f Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 23 Oct 2025 22:48:50 +0000
Subject: [PATCH 3/6] Add RSS feed validation script and example output
Co-authored-by: bradystroud <38869720+bradystroud@users.noreply.github.com>
---
_docs/RSS-Feed.md | 18 ++++++
_docs/rss-feed-example.xml | 35 ++++++++++
scripts/validate-rss-config.js | 114 +++++++++++++++++++++++++++++++++
3 files changed, 167 insertions(+)
create mode 100644 _docs/rss-feed-example.xml
create mode 100755 scripts/validate-rss-config.js
diff --git a/_docs/RSS-Feed.md b/_docs/RSS-Feed.md
index f255f48d8..8c28b1abb 100644
--- a/_docs/RSS-Feed.md
+++ b/_docs/RSS-Feed.md
@@ -47,3 +47,21 @@ Each feed item includes:
- **Date**: Last update timestamp
- **Author**: Last person who updated the rule
- **URL**: Direct link to the rule
+
+## Validation
+
+You can validate the RSS feed configuration by running:
+
+```bash
+node scripts/validate-rss-config.js
+```
+
+This script checks that:
+- The `gatsby-plugin-feed` plugin is properly configured
+- All required fields are present
+- The output path is set to `/rss.xml`
+- The feed query includes necessary data sources
+
+## Example Output
+
+See `_docs/rss-feed-example.xml` for an example of what the generated RSS feed will look like.
diff --git a/_docs/rss-feed-example.xml b/_docs/rss-feed-example.xml
new file mode 100644
index 000000000..16e0cb53e
--- /dev/null
+++ b/_docs/rss-feed-example.xml
@@ -0,0 +1,35 @@
+
+
+
+
+
+ https://www.ssw.com.au/rules
+ GatsbyJS
+ Thu, 23 Oct 2025 22:00:00 GMT
+
+ en
+
+
+
+ -
+
+
+ https://www.ssw.com.au/rules/best-practices-for-ai-prompts
+ https://www.ssw.com.au/rules/best-practices-for-ai-prompts
+
+ 2025-10-23T15:30:00.000Z
+
+
+ -
+
+
+ https://www.ssw.com.au/rules/use-semantic-html
+ https://www.ssw.com.au/rules/use-semantic-html
+
+ 2025-10-22T10:15:00.000Z
+
+
+
+
+
+
diff --git a/scripts/validate-rss-config.js b/scripts/validate-rss-config.js
new file mode 100755
index 000000000..030e52b2b
--- /dev/null
+++ b/scripts/validate-rss-config.js
@@ -0,0 +1,114 @@
+#!/usr/bin/env node
+/* eslint-disable no-console */
+
+/**
+ * This script validates the RSS feed configuration in gatsby-config.js
+ * It checks that the required configuration is present and properly structured.
+ */
+
+const path = require('path');
+
+console.log('š Validating RSS Feed Configuration...\n');
+
+try {
+ // Load gatsby-config.js
+ const configPath = path.join(__dirname, '..', 'gatsby-config.js');
+ const config = require(configPath);
+
+ // Find the RSS feed plugin
+ const feedPlugin = config.plugins.find((plugin) => {
+ if (typeof plugin === 'object' && plugin.resolve) {
+ return plugin.resolve === 'gatsby-plugin-feed';
+ }
+ return false;
+ });
+
+ if (!feedPlugin) {
+ console.error('ā gatsby-plugin-feed not found in gatsby-config.js');
+ process.exit(1);
+ }
+
+ console.log('ā
gatsby-plugin-feed found in configuration');
+
+ // Validate feed options
+ if (!feedPlugin.options) {
+ console.error('ā Feed plugin has no options');
+ process.exit(1);
+ }
+
+ console.log('ā
Feed plugin has options');
+
+ // Validate feeds array
+ if (!feedPlugin.options.feeds || !Array.isArray(feedPlugin.options.feeds)) {
+ console.error('ā Feed plugin has no feeds array');
+ process.exit(1);
+ }
+
+ console.log('ā
Feed plugin has feeds array');
+
+ // Validate first feed
+ const feed = feedPlugin.options.feeds[0];
+ if (!feed) {
+ console.error('ā No feed defined');
+ process.exit(1);
+ }
+
+ console.log('ā
Feed is defined');
+
+ // Validate feed properties
+ const requiredProps = ['serialize', 'query', 'output', 'title'];
+ const missingProps = requiredProps.filter((prop) => !feed[prop]);
+
+ if (missingProps.length > 0) {
+ console.error(
+ `ā Feed missing required properties: ${missingProps.join(', ')}`
+ );
+ process.exit(1);
+ }
+
+ console.log('ā
Feed has all required properties');
+
+ // Validate output path
+ if (feed.output !== '/rss.xml') {
+ console.error(`ā Feed output path is ${feed.output}, expected /rss.xml`);
+ process.exit(1);
+ }
+
+ console.log('ā
Feed output path is /rss.xml');
+
+ // Validate feed metadata
+ console.log('\nFeed Metadata:');
+ console.log(` Title: ${feed.title}`);
+ console.log(` Description: ${feed.description}`);
+ console.log(` Output: ${feed.output}`);
+ console.log(` Site URL: ${feed.site_url}`);
+ console.log(` Feed URL: ${feed.feed_url}`);
+
+ // Validate query includes required fields
+ const requiredQueryFields = [
+ 'allHistoryJson',
+ 'allMarkdownRemark',
+ 'lastUpdated',
+ 'lastUpdatedBy',
+ ];
+ const queryMissing = requiredQueryFields.filter(
+ (field) => !feed.query.includes(field)
+ );
+
+ if (queryMissing.length > 0) {
+ console.error(
+ `ā ļø Warning: Feed query might be missing fields: ${queryMissing.join(', ')}`
+ );
+ } else {
+ console.log('\nā
Feed query includes all expected fields');
+ }
+
+ console.log('\nā
RSS Feed configuration is valid!');
+ console.log(
+ '\nš” The RSS feed will be available at /rss.xml after the site is built.'
+ );
+ process.exit(0);
+} catch (error) {
+ console.error('ā Error validating RSS feed configuration:', error.message);
+ process.exit(1);
+}
From d0e39c2519997f17e4889fc1f6054ca3c72e3989 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 23 Oct 2025 22:51:10 +0000
Subject: [PATCH 4/6] Add comprehensive RSS feed implementation summary
Co-authored-by: bradystroud <38869720+bradystroud@users.noreply.github.com>
---
_docs/RSS-Feed-Implementation-Summary.md | 148 +++++++++++++++++++++++
1 file changed, 148 insertions(+)
create mode 100644 _docs/RSS-Feed-Implementation-Summary.md
diff --git a/_docs/RSS-Feed-Implementation-Summary.md b/_docs/RSS-Feed-Implementation-Summary.md
new file mode 100644
index 000000000..1466e26ef
--- /dev/null
+++ b/_docs/RSS-Feed-Implementation-Summary.md
@@ -0,0 +1,148 @@
+# RSS Feed Implementation - Summary
+
+## Overview
+Successfully implemented RSS feed functionality for SSW Rules to allow users to subscribe to recent rule updates.
+
+## What Was Implemented
+
+### 1. RSS Feed Plugin Installation
+- Installed `gatsby-plugin-feed@5.13.1` (latest compatible version with Gatsby 5.13.7)
+- No security vulnerabilities detected in the package
+
+### 2. RSS Feed Configuration
+- Added configuration to `gatsby-config.js`
+- Feed is generated at build time for optimal performance
+- Output location: `/rss.xml`
+- Feed includes 50 most recently updated rules
+
+### 3. Data Sources
+The RSS feed pulls from two main data sources:
+- **history.json**: Contains git commit history with update timestamps and authors
+- **Rule Markdown Files**: Contains rule content, titles, and descriptions
+
+### 4. Feed Features
+Each RSS feed entry includes:
+- Rule title
+- Description (from SEO description or excerpt)
+- Last update date and time
+- Author who made the last update
+- Direct link to the rule
+- Unique GUID for feed readers
+
+### 5. Automatic Filtering
+- Archived rules are automatically excluded from the feed
+- Rules are sorted by most recent update first
+- Limited to 50 items to keep feed size manageable
+
+### 6. Documentation
+Created comprehensive documentation including:
+- `_docs/RSS-Feed.md`: Main documentation
+- `_docs/rss-feed-example.xml`: Example of RSS feed output
+- Usage instructions
+- Technical details
+
+### 7. Validation Script
+Created `scripts/validate-rss-config.js` to:
+- Validate RSS feed configuration
+- Check required fields are present
+- Verify feed structure
+- Can be run with: `node scripts/validate-rss-config.js`
+
+## How Users Can Use It
+
+### Option 1: RSS Readers
+Users can subscribe to the feed at `https://www.ssw.com.au/rules/rss.xml` using:
+- Feedly
+- Inoreader
+- RSS Reader apps
+- Browser extensions
+
+### Option 2: Email Notifications via Power Automate
+Users can set up Power Automate to:
+1. Monitor the RSS feed
+2. Send email notifications when new updates are detected
+3. Customize notification frequency and format
+
+### Option 3: Custom Integrations
+Developers can integrate the RSS feed into:
+- Internal tools
+- Slack/Teams notifications
+- Custom dashboards
+- Monitoring systems
+
+## Feed URL
+- **Production**: https://www.ssw.com.au/rules/rss.xml
+- **Staging**: (staging-url)/rss.xml
+
+## Technical Details
+
+### Configuration Location
+```javascript
+// gatsby-config.js
+{
+ resolve: 'gatsby-plugin-feed',
+ options: {
+ feeds: [{
+ serialize: ({ query: { site, allHistoryJson, allMarkdownRemark } }) => {
+ // Custom serialization logic
+ },
+ query: `...GraphQL query...`,
+ output: '/rss.xml',
+ title: 'SSW Rules - Recent Updates',
+ description: 'Stay updated with the latest changes to SSW Rules',
+ site_url: 'https://www.ssw.com.au/rules',
+ feed_url: 'https://www.ssw.com.au/rules/rss.xml',
+ language: 'en',
+ }]
+ }
+}
+```
+
+### Build Process
+1. Gatsby runs the GraphQL query to fetch rule data and history
+2. The serialize function processes the data
+3. RSS XML is generated and written to `public/rss.xml`
+4. Feed is served as a static file
+
+## Quality Checks
+
+### ā
Linting
+All code passes ESLint checks with zero warnings/errors
+
+### ā
Security
+CodeQL analysis found no security vulnerabilities
+
+### ā
Validation
+RSS configuration validation script confirms all required fields are present
+
+## Files Changed
+1. `gatsby-config.js` - Added RSS feed configuration
+2. `package.json` - Added gatsby-plugin-feed dependency
+3. `yarn.lock` - Lock file updated
+4. `_docs/RSS-Feed.md` - Documentation
+5. `_docs/rss-feed-example.xml` - Example output
+6. `scripts/validate-rss-config.js` - Validation script
+
+## Next Steps for Testing
+Once the site is deployed:
+1. Navigate to `/rss.xml` to verify the feed is generated
+2. Validate the RSS feed using https://validator.w3.org/feed/
+3. Test subscription in an RSS reader
+4. Verify feed updates when rules are changed
+5. Create the Done Video on how to subscribe via Power Automate
+
+## Notes
+- The RSS feed is generated at build time, not on-demand
+- Feed will update whenever the site is rebuilt
+- Maximum of 50 items ensures feed size stays manageable
+- Archived rules are automatically excluded
+- Feed uses standard RSS 2.0 format with Dublin Core extensions
+
+## Maintenance
+The RSS feed requires no ongoing maintenance. It will automatically:
+- Update when rules are changed and the site is rebuilt
+- Exclude archived rules
+- Sort by most recent updates
+- Include proper metadata
+
+If changes to the feed are needed, edit the configuration in `gatsby-config.js` and run the validation script to ensure the configuration is still valid.
From d209e169cf1ea4db00e60888e1b2d632f74567e3 Mon Sep 17 00:00:00 2001
From: "Brady Stroud [SSW]"
Date: Fri, 14 Nov 2025 08:12:40 +1100
Subject: [PATCH 5/6] Remove obsolete RSS feed documentation and example output
files
---
_docs/RSS-Feed-Implementation-Summary.md | 148 -----------------------
_docs/RSS-Feed.md | 67 ----------
_docs/rss-feed-example.xml | 35 ------
3 files changed, 250 deletions(-)
delete mode 100644 _docs/RSS-Feed-Implementation-Summary.md
delete mode 100644 _docs/RSS-Feed.md
delete mode 100644 _docs/rss-feed-example.xml
diff --git a/_docs/RSS-Feed-Implementation-Summary.md b/_docs/RSS-Feed-Implementation-Summary.md
deleted file mode 100644
index 1466e26ef..000000000
--- a/_docs/RSS-Feed-Implementation-Summary.md
+++ /dev/null
@@ -1,148 +0,0 @@
-# RSS Feed Implementation - Summary
-
-## Overview
-Successfully implemented RSS feed functionality for SSW Rules to allow users to subscribe to recent rule updates.
-
-## What Was Implemented
-
-### 1. RSS Feed Plugin Installation
-- Installed `gatsby-plugin-feed@5.13.1` (latest compatible version with Gatsby 5.13.7)
-- No security vulnerabilities detected in the package
-
-### 2. RSS Feed Configuration
-- Added configuration to `gatsby-config.js`
-- Feed is generated at build time for optimal performance
-- Output location: `/rss.xml`
-- Feed includes 50 most recently updated rules
-
-### 3. Data Sources
-The RSS feed pulls from two main data sources:
-- **history.json**: Contains git commit history with update timestamps and authors
-- **Rule Markdown Files**: Contains rule content, titles, and descriptions
-
-### 4. Feed Features
-Each RSS feed entry includes:
-- Rule title
-- Description (from SEO description or excerpt)
-- Last update date and time
-- Author who made the last update
-- Direct link to the rule
-- Unique GUID for feed readers
-
-### 5. Automatic Filtering
-- Archived rules are automatically excluded from the feed
-- Rules are sorted by most recent update first
-- Limited to 50 items to keep feed size manageable
-
-### 6. Documentation
-Created comprehensive documentation including:
-- `_docs/RSS-Feed.md`: Main documentation
-- `_docs/rss-feed-example.xml`: Example of RSS feed output
-- Usage instructions
-- Technical details
-
-### 7. Validation Script
-Created `scripts/validate-rss-config.js` to:
-- Validate RSS feed configuration
-- Check required fields are present
-- Verify feed structure
-- Can be run with: `node scripts/validate-rss-config.js`
-
-## How Users Can Use It
-
-### Option 1: RSS Readers
-Users can subscribe to the feed at `https://www.ssw.com.au/rules/rss.xml` using:
-- Feedly
-- Inoreader
-- RSS Reader apps
-- Browser extensions
-
-### Option 2: Email Notifications via Power Automate
-Users can set up Power Automate to:
-1. Monitor the RSS feed
-2. Send email notifications when new updates are detected
-3. Customize notification frequency and format
-
-### Option 3: Custom Integrations
-Developers can integrate the RSS feed into:
-- Internal tools
-- Slack/Teams notifications
-- Custom dashboards
-- Monitoring systems
-
-## Feed URL
-- **Production**: https://www.ssw.com.au/rules/rss.xml
-- **Staging**: (staging-url)/rss.xml
-
-## Technical Details
-
-### Configuration Location
-```javascript
-// gatsby-config.js
-{
- resolve: 'gatsby-plugin-feed',
- options: {
- feeds: [{
- serialize: ({ query: { site, allHistoryJson, allMarkdownRemark } }) => {
- // Custom serialization logic
- },
- query: `...GraphQL query...`,
- output: '/rss.xml',
- title: 'SSW Rules - Recent Updates',
- description: 'Stay updated with the latest changes to SSW Rules',
- site_url: 'https://www.ssw.com.au/rules',
- feed_url: 'https://www.ssw.com.au/rules/rss.xml',
- language: 'en',
- }]
- }
-}
-```
-
-### Build Process
-1. Gatsby runs the GraphQL query to fetch rule data and history
-2. The serialize function processes the data
-3. RSS XML is generated and written to `public/rss.xml`
-4. Feed is served as a static file
-
-## Quality Checks
-
-### ā
Linting
-All code passes ESLint checks with zero warnings/errors
-
-### ā
Security
-CodeQL analysis found no security vulnerabilities
-
-### ā
Validation
-RSS configuration validation script confirms all required fields are present
-
-## Files Changed
-1. `gatsby-config.js` - Added RSS feed configuration
-2. `package.json` - Added gatsby-plugin-feed dependency
-3. `yarn.lock` - Lock file updated
-4. `_docs/RSS-Feed.md` - Documentation
-5. `_docs/rss-feed-example.xml` - Example output
-6. `scripts/validate-rss-config.js` - Validation script
-
-## Next Steps for Testing
-Once the site is deployed:
-1. Navigate to `/rss.xml` to verify the feed is generated
-2. Validate the RSS feed using https://validator.w3.org/feed/
-3. Test subscription in an RSS reader
-4. Verify feed updates when rules are changed
-5. Create the Done Video on how to subscribe via Power Automate
-
-## Notes
-- The RSS feed is generated at build time, not on-demand
-- Feed will update whenever the site is rebuilt
-- Maximum of 50 items ensures feed size stays manageable
-- Archived rules are automatically excluded
-- Feed uses standard RSS 2.0 format with Dublin Core extensions
-
-## Maintenance
-The RSS feed requires no ongoing maintenance. It will automatically:
-- Update when rules are changed and the site is rebuilt
-- Exclude archived rules
-- Sort by most recent updates
-- Include proper metadata
-
-If changes to the feed are needed, edit the configuration in `gatsby-config.js` and run the validation script to ensure the configuration is still valid.
diff --git a/_docs/RSS-Feed.md b/_docs/RSS-Feed.md
deleted file mode 100644
index 8c28b1abb..000000000
--- a/_docs/RSS-Feed.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# RSS Feed
-
-SSW Rules provides an RSS feed for recent rules changes at `/rss.xml`.
-
-## Overview
-
-The RSS feed is generated during the build process using the `gatsby-plugin-feed` plugin. It provides:
-
-- The 50 most recently updated rules
-- Automatic filtering of archived rules
-- Information about who made the last update
-- Links to the updated rules
-- Rule descriptions from the SEO description or excerpt
-
-## Feed URL
-
-The RSS feed is available at:
-- Production: `https://www.ssw.com.au/rules/rss.xml`
-- Staging: Check the staging deployment URL and append `/rss.xml`
-
-## Usage
-
-Users can subscribe to this RSS feed using:
-- RSS readers (e.g., Feedly, Inoreader)
-- Email notifications via Power Automate or similar automation tools
-- Custom integrations
-
-## Configuration
-
-The RSS feed is configured in `gatsby-config.js` with the `gatsby-plugin-feed` plugin. The feed:
-
-1. Queries the `history.json` data for recent rule updates
-2. Sorts by `lastUpdated` date in descending order
-3. Filters out archived rules
-4. Limits to the 50 most recent updates
-5. Includes metadata such as title, description, author, and publication date
-
-## Technical Details
-
-The feed uses the following data sources:
-- `allHistoryJson`: Git history data sorted by last update date
-- `allMarkdownRemark`: Rule content including title, excerpt, and SEO description
-
-Each feed item includes:
-- **Title**: The rule title
-- **Description**: SEO description, excerpt, or update information
-- **Date**: Last update timestamp
-- **Author**: Last person who updated the rule
-- **URL**: Direct link to the rule
-
-## Validation
-
-You can validate the RSS feed configuration by running:
-
-```bash
-node scripts/validate-rss-config.js
-```
-
-This script checks that:
-- The `gatsby-plugin-feed` plugin is properly configured
-- All required fields are present
-- The output path is set to `/rss.xml`
-- The feed query includes necessary data sources
-
-## Example Output
-
-See `_docs/rss-feed-example.xml` for an example of what the generated RSS feed will look like.
diff --git a/_docs/rss-feed-example.xml b/_docs/rss-feed-example.xml
deleted file mode 100644
index 16e0cb53e..000000000
--- a/_docs/rss-feed-example.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-
-
-
-
-
- https://www.ssw.com.au/rules
- GatsbyJS
- Thu, 23 Oct 2025 22:00:00 GMT
-
- en
-
-
-
- -
-
-
- https://www.ssw.com.au/rules/best-practices-for-ai-prompts
- https://www.ssw.com.au/rules/best-practices-for-ai-prompts
-
- 2025-10-23T15:30:00.000Z
-
-
- -
-
-
- https://www.ssw.com.au/rules/use-semantic-html
- https://www.ssw.com.au/rules/use-semantic-html
-
- 2025-10-22T10:15:00.000Z
-
-
-
-
-
-
From 32dc492044ea7c53f5b8d5a31b58c68f65905ffa Mon Sep 17 00:00:00 2001
From: "Brady Stroud [SSW]"
Date: Fri, 14 Nov 2025 11:29:58 +1100
Subject: [PATCH 6/6] Fix RSS feed GUID assignment to use rule frontmatter
---
gatsby-config.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gatsby-config.js b/gatsby-config.js
index 5ac1361e2..e38f56011 100644
--- a/gatsby-config.js
+++ b/gatsby-config.js
@@ -82,7 +82,7 @@ module.exports = {
`Updated by ${edge.node.lastUpdatedBy}`,
date: edge.node.lastUpdated,
url: url,
- guid: url,
+ guid: rule.frontmatter.guid,
custom_elements: [
{ 'dc:creator': edge.node.lastUpdatedBy },
{ pubDate: edge.node.lastUpdated },