summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--srv/src/api/api.go1
-rw-r--r--srv/src/api/render.go14
-rw-r--r--srv/src/api/tpl/follow.html152
3 files changed, 167 insertions, 0 deletions
diff --git a/srv/src/api/api.go b/srv/src/api/api.go
index 7323d29..0184ef1 100644
--- a/srv/src/api/api.go
+++ b/srv/src/api/api.go
@@ -194,6 +194,7 @@ func (a *api) handler() http.Handler {
mux.Handle("/api/", http.StripPrefix("/api", apiHandler))
// TODO need to setCSRFMiddleware on all these rendering endpoints
+ mux.Handle("/v2/follow.html", a.renderDumbHandler("follow.html"))
mux.Handle("/v2/posts/", a.renderPostHandler())
mux.Handle("/v2/", a.renderIndexHandler())
diff --git a/srv/src/api/render.go b/srv/src/api/render.go
index 2b6b5a0..0f45211 100644
--- a/srv/src/api/render.go
+++ b/srv/src/api/render.go
@@ -178,3 +178,17 @@ func (a *api) renderPostHandler() http.Handler {
}
})
}
+
+func (a *api) renderDumbHandler(tplName string) http.Handler {
+
+ tpl := a.mustParseTpl(tplName)
+
+ return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
+ if err := tpl.Execute(rw, nil); err != nil {
+ apiutil.InternalServerError(
+ rw, r, fmt.Errorf("rendering %q: %w", tplName, err),
+ )
+ return
+ }
+ })
+}
diff --git a/srv/src/api/tpl/follow.html b/srv/src/api/tpl/follow.html
new file mode 100644
index 0000000..8cf9dc6
--- /dev/null
+++ b/srv/src/api/tpl/follow.html
@@ -0,0 +1,152 @@
+{{ define "body" }}
+
+<script async type="module" src="/assets/api.js"></script>
+
+<p>
+ Here's your options for receiving updates about new blog posts:
+</p>
+
+<h2>Option 1: Email</h2>
+
+<p>
+ Email is by far my preferred option for notifying followers of new posts.
+</p>
+
+<p>
+ The entire email list system for this blog, from storing subscriber email
+ addresses to the email server which sends the notifications out, has been
+ designed from scratch and is completely self-hosted in my living room.
+</p>
+
+<p>
+ I solemnly swear that:
+</p>
+
+<ul>
+
+ <li>
+ You will never receive an email from this blog except to notify of a new
+ post.
+ </li>
+
+ <li>
+ Your email will never be provided or sold to anyone else for any reason.
+ </li>
+
+</ul>
+
+<p>
+ With all that said, if you'd like to receive an email everytime a new blog
+ post is published then input your email below and smash that subscribe button!
+ You will need to verify your email, so be sure to check your spam folder to
+ complete the process if you don't immediately see anything in your inbox.
+</p>
+
+<style>
+
+#emailStatus.success {
+ color: green;
+}
+
+#emailStatus.fail {
+ color: red;
+}
+
+</style>
+
+<input type="email" placeholder="name@host.com" id="emailAddress" />
+<input class="button-primary" type="submit" value="Subscribe" id="emailSubscribe" />
+<span id="emailStatus"></span>
+
+<script>
+
+const emailAddress = document.getElementById("emailAddress");
+const emailSubscribe = document.getElementById("emailSubscribe");
+const emailSubscribeOrigValue = emailSubscribe.value;
+const emailStatus = document.getElementById("emailStatus");
+
+emailSubscribe.onclick = async () => {
+
+ const api = await import("/assets/api.js");
+
+ emailSubscribe.disabled = true;
+ emailSubscribe.className = "";
+ emailSubscribe.value = "Please hold...";
+ emailStatus.innerHTML = '';
+
+ try {
+
+ if (!window.isSecureContext) {
+ throw "The browser environment is not secure.";
+ }
+
+ await api.call('/api/mailinglist/subscribe', {
+ body: { email: emailAddress.value },
+ requiresPow: true,
+ });
+
+ emailStatus.className = "success";
+ emailStatus.innerHTML = "Verification email sent (check your spam folder)";
+
+ } catch (e) {
+ emailStatus.className = "fail";
+ emailStatus.innerHTML = e;
+
+ } finally {
+ emailSubscribe.disabled = false;
+ emailSubscribe.className = "button-primary";
+ emailSubscribe.value = emailSubscribeOrigValue;
+ }
+
+};
+
+</script>
+
+<h2>Option 2: RSS</h2>
+
+<p>
+ RSS is the classic way to follow any blog. It comes from a time before
+ aggregators like reddit and twitter stole the show, when people felt capable
+ to manage their own content feeds. We should use it again.
+</p>
+
+<p>
+ To follow over RSS give any RSS reader the following URL...
+</p>
+
+<p>
+ <a href="{{ BlogURL "feed.xml" }}">{{ BlogURL "feed.xml" }}</a>
+</p>
+
+<p>
+ ...and posts from this blog will show up in your RSS feed as soon as they are
+ published. There are literally thousands of RSS readers out there. Here's some
+ recommendations:
+</p>
+
+<ul>
+ <li>
+ <a href="https://chrome.google.com/webstore/detail/rss-feed-reader/pnjaodmkngahhkoihejjehlcdlnohgmp">
+ Google Chrome Browser Extension
+ </a>
+ </li>
+
+ <li>
+ <a href="https://f-droid.org/en/packages/net.etuldan.sparss.floss/">
+ spaRSS
+ </a>
+ is my preferred android RSS reader, but you'll need to install
+ <a href="https://f-droid.org/">f-droid</a> on your device to use it (a
+ good thing to do anyway, imo).
+ </li>
+
+ <li>
+ <a href="https://ranchero.com/netnewswire/">NetNewsWire</a>
+ is a good reader for iPhone/iPad/Mac devices, so I'm told. Their homepage
+ description makes a much better sales pitch for RSS than I ever could.
+ </li>
+</ul>
+
+{{ end }}
+
+{{ template "base.html" . }}