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 @@ + + + + <![CDATA[SSW Rules - Recent Updates]]> + + https://www.ssw.com.au/rules + GatsbyJS + Thu, 23 Oct 2025 22:00:00 GMT + + en + + + + + <![CDATA[Do you know the best practices for AI prompts?]]> + + 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 + + + + <![CDATA[Do you use semantic HTML?]]> + + 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 @@ - - - - <![CDATA[SSW Rules - Recent Updates]]> - - https://www.ssw.com.au/rules - GatsbyJS - Thu, 23 Oct 2025 22:00:00 GMT - - en - - - - - <![CDATA[Do you know the best practices for AI prompts?]]> - - 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 - - - - <![CDATA[Do you use semantic HTML?]]> - - 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 },