{"action":"created","issue":{"url":"https://api.github.com/repos/gatsbyjs/gatsby/issues/3489","repository_url":"https://api.github.com/repos/gatsbyjs/gatsby","labels_url":"https://api.github.com/repos/gatsbyjs/gatsby/issues/3489/labels{/name}","comments_url":"https://api.github.com/repos/gatsbyjs/gatsby/issues/3489/comments","events_url":"https://api.github.com/repos/gatsbyjs/gatsby/issues/3489/events","html_url":"https://github.com/gatsbyjs/gatsby/issues/3489","id":287971189,"node_id":"MDU6SXNzdWUyODc5NzExODk=","number":3489,"title":"gatsby-plugin-feed feature request - dynamic feeds","user":{"login":"agarrharr","id":3266363,"node_id":"MDQ6VXNlcjMyNjYzNjM=","avatar_url":"https://avatars2.githubusercontent.com/u/3266363?v=4","gravatar_id":"","url":"https://api.github.com/users/agarrharr","html_url":"https://github.com/agarrharr","followers_url":"https://api.github.com/users/agarrharr/followers","following_url":"https://api.github.com/users/agarrharr/following{/other_user}","gists_url":"https://api.github.com/users/agarrharr/gists{/gist_id}","starred_url":"https://api.github.com/users/agarrharr/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/agarrharr/subscriptions","organizations_url":"https://api.github.com/users/agarrharr/orgs","repos_url":"https://api.github.com/users/agarrharr/repos","events_url":"https://api.github.com/users/agarrharr/events{/privacy}","received_events_url":"https://api.github.com/users/agarrharr/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":4,"created_at":"2018-01-12T00:29:07Z","updated_at":"2018-09-08T04:06:35Z","closed_at":"2018-09-08T04:06:35Z","author_association":"CONTRIBUTOR","body":"@nicholaswyoung \r\n\r\n## Description\r\n\r\nAs a user of `gatsby-plugin-feed`, I would like to be able to dynamically generate feeds. For example, I have a website that has multiple podcasts. I want to generate an rss feed for each of them automatically based on the data from Contentful (at `podcastname/feed.rss`). I also want a master feed at `master.rss`.\r\n\r\n### Environment\r\n\r\nGatsby version: ^1.9.145\r\nNode.js version: v8.7.0\r\nOperating System: macOS High Sierra 10.13.2\r\n\r\n### Example\r\n\r\n```\r\n  plugins: [\r\n    {\r\n      resolve: `gatsby-plugin-feed`,\r\n      options: {\r\n        query: `\r\n        {\r\n          ...\r\n        }\r\n      `,\r\n        feeds: ({query}) => {\r\n          ...Here is where I would like to dynamically generate an array of feeds to return...\r\n        },\r\n```\r\n\r\nI have actually done this with a small modification to the plugin, which I can submit as a pull request.\r\n\r\nHere is an example of what I did.\r\n\r\n```js\r\n// gatsby-config.js\r\nrequire('dotenv').config();\r\nconst { DateTime } = require('luxon');\r\nvar humanizeList = require('humanize-list');\r\n\r\nconst serialize = podcast =>\r\n  podcast.episode\r\n    ? podcast.episode.map(episode => ({\r\n        title: episode.name,\r\n        description:\r\n          episode.shortDescription || `Episode ${episode.episodeNumber}`,\r\n        url: episode.audioUrl,\r\n        guid: episode.id,\r\n        author: episode.hosts.map(h => h.name, {\r\n          oxfordComma: true,\r\n        }),\r\n        enclosure: {\r\n          url: episode.audioUrl,\r\n          length: episode.audioLength,\r\n          type: 'audio/mp3',\r\n        },\r\n        custom_elements: [\r\n          {\r\n            pubDate: DateTime.fromISO(episode.publicationDate).toHTTP(),\r\n          },\r\n          {\r\n            'itunes:author': humanizeList(\r\n              episode.hosts.map(h => h.name, { oxfordComma: true })\r\n            ),\r\n          },\r\n          {\r\n            'itunes:subtitle': episode.shortDescription,\r\n          },\r\n          {\r\n            'itunes:summary': episode.shortDescription,\r\n          },\r\n          {\r\n            'content:encoded': `<p>${episode.shortDescription}</p>${\r\n              episode.fields ? episode.fields.showNotesFormatted : ``\r\n            }`,\r\n          },\r\n          { 'itunes:explicit': 'clean' },\r\n          {\r\n            'itunes:image': {\r\n              _attr: {\r\n                href: episode.image\r\n                  ? episode.image.file.url\r\n                  : podcast.image ? podcast.image.file.url : ``,\r\n              },\r\n            },\r\n          },\r\n          { 'itunes:duration': episode.duration },\r\n        ],\r\n      }))\r\n    : [];\r\n\r\nmodule.exports = {\r\n  siteMetadata: {\r\n    title: `Orbit FM`,\r\n    description: `Orbit FM is a place with podcasts.`,\r\n    siteUrl: `http://www.orbit.fm`,\r\n    owner: `Orbit FM`,\r\n    ownerEmail: `hello@orbit.fm`,\r\n    categories: ['Technology', 'Education'],\r\n  },\r\n  plugins: [\r\n    {\r\n      resolve: `gatsby-plugin-podcast-feed`,\r\n      options: {\r\n        query: `\r\n        {\r\n          site {\r\n            siteMetadata {\r\n              title\r\n              description\r\n              siteUrl\r\n              owner\r\n              ownerEmail\r\n              categories\r\n            }\r\n          }\r\n          allContentfulPodcast {\r\n            edges {\r\n              node {\r\n                id\r\n                image {\r\n                  file {\r\n                    url\r\n                  }\r\n                }\r\n                fields {\r\n                  slug\r\n                }\r\n                episode {\r\n                  id\r\n                  episodeNumber\r\n                  audioUrl\r\n                  name\r\n                  shortDescription\r\n                  publicationDate\r\n                  audioLength\r\n                  duration\r\n                  hosts {\r\n                    name\r\n                  }\r\n                  fields {\r\n                    showNotesFormatted\r\n                  }\r\n                }\r\n              }\r\n            }\r\n          }\r\n        }\r\n      `,\r\n        setup: ({\r\n          query: { site: { siteMetadata }, allContentfulPodcast },\r\n        }) => {\r\n          const podcast = allContentfulPodcast.edges[0].node;\r\n          return {\r\n            title: siteMetadata.title,\r\n            description: siteMetadata.description,\r\n            feed_url: `${siteMetadata.siteUrl}/${podcast.fields.slug}/feed.rss`,\r\n            site_url: siteMetadata.siteUrl,\r\n            image_url: podcast.image ? podcast.image.file.url : ``,\r\n            managingEditor: `${siteMetadata.ownerEmail} (${\r\n              siteMetadata.owner\r\n            })`,\r\n            webMaster: `${siteMetadata.ownerEmail} (${siteMetadata.owner})`,\r\n            copyright: `${new Date().getFullYear()} ${siteMetadata.owner}`,\r\n            language: 'en',\r\n            categories: siteMetadata.categories,\r\n            pubDate: DateTime.fromISO(new Date()).toHTTP(),\r\n            ttl: '60',\r\n            custom_namespaces: {\r\n              itunes: 'http://www.itunes.com/dtds/podcast-1.0.dtd',\r\n            },\r\n            custom_elements: [\r\n              { 'itunes:subtitle': siteMetadata.description },\r\n              { 'itunes:author': siteMetadata.owner },\r\n              { 'itunes:explicit': 'clean' },\r\n              {\r\n                'itunes:summary': siteMetadata.description,\r\n              },\r\n              {\r\n                'itunes:owner': [\r\n                  { 'itunes:name': siteMetadata.owner },\r\n                  { 'itunes:email': siteMetadata.ownerEmail },\r\n                ],\r\n              },\r\n              {\r\n                'itunes:image': {\r\n                  _attr: {\r\n                    href: podcast.image ? podcast.image.file.url : ``,\r\n                  },\r\n                },\r\n              },\r\n              ...siteMetadata.categories.map(c => ({\r\n                'itunes:category': {\r\n                  _attr: {\r\n                    text: c,\r\n                  },\r\n                },\r\n              })),\r\n            ],\r\n          };\r\n        },\r\n        feeds: ({\r\n          query: { site: { siteMetadata }, allContentfulPodcast },\r\n        }) => [\r\n          ...allContentfulPodcast.edges.map(({ node }, i) => ({\r\n            serialize: ({ query: { site, allContentfulPodcast } }) =>\r\n              serialize(allContentfulPodcast.edges[i].node),\r\n            output: `${node.fields.slug}/feed.rss`,\r\n          })),\r\n          {\r\n            serialize: ({ query: { site, allContentfulPodcast } }) =>\r\n              serialize({\r\n                image: {\r\n                  file: {\r\n                    url: 'testImage',\r\n                  },\r\n                },\r\n                fields: {\r\n                  slug: 'master',\r\n                },\r\n                episode: allContentfulPodcast.edges.reduce(\r\n                  (a, { node }) => [...a, ...(node.episode || [])],\r\n                  []\r\n                ),\r\n              }),\r\n            output: `master.rss`,\r\n          },\r\n        ],\r\n      },\r\n    },\r\n\r\n    `gatsby-plugin-react-helmet`,\r\n    `gatsby-plugin-emotion`,\r\n    {\r\n      resolve: `gatsby-plugin-typography`,\r\n      options: {\r\n        pathToConfigModule: `src/utils/typography.js`,\r\n      },\r\n    },\r\n    {\r\n      resolve: `gatsby-source-contentful`,\r\n      options: {\r\n        spaceId: process.env.CONTENTFUL_SPACE_ID,\r\n        accessToken: process.env.CONTENTFUL_ACCESS_TOKEN,\r\n      },\r\n    },\r\n  ],\r\n};\r\n```\r\n"},"comment":{"url":"https://api.github.com/repos/gatsbyjs/gatsby/issues/comments/419610964","html_url":"https://github.com/gatsbyjs/gatsby/issues/3489#issuecomment-419610964","issue_url":"https://api.github.com/repos/gatsbyjs/gatsby/issues/3489","id":419610964,"node_id":"MDEyOklzc3VlQ29tbWVudDQxOTYxMDk2NA==","user":{"login":"KyleAMathews","id":71047,"node_id":"MDQ6VXNlcjcxMDQ3","avatar_url":"https://avatars3.githubusercontent.com/u/71047?v=4","gravatar_id":"","url":"https://api.github.com/users/KyleAMathews","html_url":"https://github.com/KyleAMathews","followers_url":"https://api.github.com/users/KyleAMathews/followers","following_url":"https://api.github.com/users/KyleAMathews/following{/other_user}","gists_url":"https://api.github.com/users/KyleAMathews/gists{/gist_id}","starred_url":"https://api.github.com/users/KyleAMathews/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/KyleAMathews/subscriptions","organizations_url":"https://api.github.com/users/KyleAMathews/orgs","repos_url":"https://api.github.com/users/KyleAMathews/repos","events_url":"https://api.github.com/users/KyleAMathews/events{/privacy}","received_events_url":"https://api.github.com/users/KyleAMathews/received_events","type":"User","site_admin":false},"created_at":"2018-09-08T04:06:35Z","updated_at":"2018-09-08T04:06:35Z","author_association":"CONTRIBUTOR","body":"Due to the high volume of issues, we're closing out older ones without recent activity. Please open a new issue if you need help!"}}
{"actor":{"display_login":"KyleAMathews"}}