diff --git a/blog.tmpl.html b/blog.tmpl.html
index 8cfc217..855bfbf 100644
--- a/blog.tmpl.html
+++ b/blog.tmpl.html
@@ -5,6 +5,7 @@
+
diff --git a/feed.tmpl.xml b/feed.tmpl.xml
new file mode 100644
index 0000000..bedddb2
--- /dev/null
+++ b/feed.tmpl.xml
@@ -0,0 +1,19 @@
+
+
+
+ tilde.town blog
+ web log of tilde town
+ https://tilde.town/blog.html
+
+ {{ range .News }}
+ -
+ {{.Title}}
+ {{.Pubdate}}
+
+
+
+ {{.Pubdate}}-{{.Title}}
+
+ {{ end }}
+
+
diff --git a/generate_homepage b/generate_homepage
index 6344b92..6dec788 100644
--- a/generate_homepage
+++ b/generate_homepage
@@ -6,5 +6,6 @@ set -e
cd /town/src/tilde.town
/usr/bin/go run genblog.go > blog.html
+/usr/bin/go run genfeed.go > blog.xml
/usr/bin/go run genusers.go > users.html
-/bin/cp index.html blog.html users.html blog.css style.css /var/www/tilde.town/
+/bin/cp index.html blog.html blog.xml users.html blog.css style.css /var/www/tilde.town/
diff --git a/genfeed.go b/genfeed.go
new file mode 100644
index 0000000..54e9119
--- /dev/null
+++ b/genfeed.go
@@ -0,0 +1,83 @@
+package main
+
+import (
+ "bytes"
+ _ "embed"
+ "encoding/json"
+ "fmt"
+ "os"
+ "os/exec"
+ "text/template"
+)
+
+const statsPath = "/usr/local/bin/stats"
+
+//go:embed feed.tmpl.xml
+var feedTmpl string
+
+type newsEntry struct {
+ Title string // Title of entry
+ Pubdate string // Human readable date
+ Content string // HTML of entry
+}
+
+type tildeData struct {
+ News []newsEntry
+}
+
+func _main() error {
+ data, err := stats()
+ if err != nil {
+ return err
+ }
+
+ type tmplData struct {
+ News []newsEntry
+ }
+
+ td := &tmplData{
+ News: data.News,
+ }
+
+ t, err := template.New("feed").Parse(feedTmpl)
+ if err != nil {
+ return fmt.Errorf("failed to parse the feed template: %w", err)
+ }
+
+ out := bytes.Buffer{}
+ if err = t.Execute(&out, td); err != nil {
+ return fmt.Errorf("failed to render feed template: %w", err)
+ }
+
+ fmt.Println(out.String())
+
+ return nil
+}
+
+func stats() (*tildeData, error) {
+ sout := bytes.Buffer{}
+ cmd := exec.Command(statsPath)
+ cmd.Stdout = &sout
+
+ err := cmd.Run()
+ if err != nil {
+ return nil, err
+ }
+
+ var data tildeData
+
+ err = json.Unmarshal(sout.Bytes(), &data)
+ if err != nil {
+ return nil, err
+ }
+
+ return &data, nil
+}
+
+func main() {
+ err := _main()
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "error: %s\n", err)
+ os.Exit(1)
+ }
+}