--- /dev/null
+;;; Copyright © 2019 Amin Bandali <bandali@gnu.org>
+;;;
+;;; This program is free software; you can redistribute it and/or
+;;; modify it under the terms of the GNU General Public License as
+;;; published by the Free Software Foundation; either version 3 of the
+;;; License, or (at your option) any later version.
+;;;
+;;; This program is distributed in the hope that it will be useful,
+;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;;; General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with this program. If not, see
+;;; <http://www.gnu.org/licenses/>.
+
+(define-module (bandali feeds)
+ #:use-module (haunt builder atom) ; atom-feed
+ #:use-module (haunt builder rss) ; rss-feed
+ #:use-module (haunt post) ; post-*
+ #:use-module (ice-9 match) ; match-lambda
+ #:re-export (atom-feed
+ rss-feed)
+ #:export (atom-feeds-by-tag
+ rss-feeds-by-tag))
+
+(define* (atom-feeds-by-tag #:key
+ (prefix "feeds/tags")
+ (filter posts/reverse-chronological)
+ (max-entries 20)
+ (blog-prefix ""))
+ "Return a builder procedure that renders an atom feed for every tag
+used in a post. All arguments are optional:
+
+PREFIX: The directory in which to write the feeds
+FILTER: The procedure called to manipulate the posts list before rendering
+MAX-ENTRIES: The maximum number of posts to render in each feed"
+ (lambda (site posts)
+ (let ((tag-groups (posts/group-by-tag posts)))
+ (map (match-lambda
+ ((tag . posts)
+ ((atom-feed #:file-name (string-append prefix "/" tag ".atom")
+ #:subtitle (string-append "Tag: " tag)
+ #:filter filter
+ #:max-entries max-entries
+ #:blog-prefix blog-prefix)
+ site posts)))
+ tag-groups))))
+
+(define* (rss-feeds-by-tag #:key
+ (prefix "feeds/tags")
+ (filter posts/reverse-chronological)
+ (max-entries 20)
+ (blog-prefix ""))
+ "Return a builder procedure that renders an rss feed for every tag
+used in a post. All arguments are optional:
+
+PREFIX: The directory in which to write the feeds
+FILTER: The procedure called to manipulate the posts list before rendering
+MAX-ENTRIES: The maximum number of posts to render in each feed"
+ (lambda (site posts)
+ (let ((tag-groups (posts/group-by-tag posts)))
+ (map (match-lambda
+ ((tag . posts)
+ ((rss-feed #:file-name (string-append prefix "/" tag ".rss")
+ #:subtitle (string-append "Tag: " tag)
+ #:filter filter
+ #:max-entries max-entries
+ #:blog-prefix blog-prefix)
+ site posts)))
+ tag-groups))))