From 6d331c6bf6ecfebff01d08598096b7344423bef4 Mon Sep 17 00:00:00 2001 From: Hugo Thunnissen Date: Sat, 8 Feb 2020 19:20:47 +0100 Subject: [PATCH] Add Post: Creating a simple static blog --- blog.html | 9 +- feed.xml | 10 +- generate-blog.bash.html | 269 ++++++++++++++++++++++ posts.txt | 1 + posts/simple-static-blog/index.html | 205 +++++++++++++++++ posts/simple-static-blog/publish_date.txt | 1 + 6 files changed, 492 insertions(+), 3 deletions(-) create mode 100644 generate-blog.bash.html create mode 100644 posts/simple-static-blog/index.html create mode 100644 posts/simple-static-blog/publish_date.txt diff --git a/blog.html b/blog.html index ddff6af..5a986d5 100644 --- a/blog.html +++ b/blog.html @@ -39,7 +39,14 @@

Blog

-

Introduction

+

Creating a Simple Static Blog

+Sat 08 Feb 2020 12:14:16 PM CET

I love personal websites. It's amazing that people can share content with the +entire world just by writing some text and throwing it on a web server. I +wanted to know what that is like, so I set out to create a personal website of +my own. As you can see I succeeded in the end. But getting here wasn't as +straight forward as I initially thought it would be. I thought that, being a ... Continue reading

+
+

Introduction

Sat 08 Feb 2020 09:30:06 AM CET

Hello, welcome to my blog! My name is Hugo. I am a 22 year old Software Engineering student from the Netherlands. Software development is a huge part of my life, I write a lot of (weird) programs to scratch my own itch and most diff --git a/feed.xml b/feed.xml index 2aa8a55..a364902 100644 --- a/feed.xml +++ b/feed.xml @@ -5,12 +5,18 @@ https://hugot.nl/blog.html Hugo's personal blog en-us - Sat 08 Feb 2020 10:41:46 AM CET - Sat 08 Feb 2020 10:41:46 AM CET + Sat 08 Feb 2020 05:04:18 PM CET + Sat 08 Feb 2020 05:04:18 PM CET http://blogs.law.harvard.edu/tech/rss Hugo's Custom Bash Script social@hugot.nl infra@hugot.nl + Creating a Simple Static Blog https://hugot.nl/posts/simple-static-blog/index.htmlI love personal websites. It's amazing that people can share content with the +entire world just by writing some text and throwing it on a web server. I +wanted to know what that is like, so I set out to create a personal website of +my own. As you can see I succeeded in the end. But getting here wasn't as +straight forward as I initially thought it would be. I thought that, being aSat 08 Feb 2020 12:14:16 PM CET Creating a Simple Static Blog Mzk2MDM4MTY0MCAyNjg0Cg== + Introduction https://hugot.nl/posts/introduction/index.htmlHello, welcome to my blog! My name is Hugo. I am a 22 year old Software Engineering student from the Netherlands. Software development is a huge part of my life, I write a lot of (weird) programs to scratch my own itch and most diff --git a/generate-blog.bash.html b/generate-blog.bash.html new file mode 100644 index 0000000..b2f5783 --- /dev/null +++ b/generate-blog.bash.html @@ -0,0 +1,269 @@ + + + + + generate-blog.bash + + + +

+#!/bin/bash
+##
+# Generate html page with blog article excerpts from ./posts.txt.  Post file names should
+# be added to ./posts.txt in the exact order that they are supposed to appear on the blog
+# page.
+
+# Check if required executables can be found
+if ! type readlink dirname html2text mv cat cksum base64; then
+    echo 'One or more required executables are not present. Generation cancelled' >&2
+    exit 1
+fi
+
+# Determine script directory (requires GNU readlink)
+here="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"
+
+printf 'Changing directory: '
+pushd "$here" || exit  $?
+
+posts_file="$here/posts.txt"
+
+if ! [[ -f "$posts_file" ]]; then
+    printf 'Posts file "%s" not found. Generation cancelled.\n' "$posts_file" >&2
+    exit 1
+fi
+
+escape-html() {
+    sed 's/&/\&amp;/g; s/</\&lt;/g; s/>/\&gt;/g; s/"/\&quot;/g; s/'"'"'/\&#39;/g'
+}
+
+html-to-text() {
+    html2text -nobs -style compact "$@"
+}
+
+print-blog-html-top() {
+    echo '<html>
+    <head>
+        <title>Blog</title>
+        <meta charset="UTF-8">
+    </head>
+
+    <style type="text/css">
+     html {
+         font-family: Helvetica, Arial, sans-serif;
+         color: #5b4636;
+         background-color: #f4ecd8;
+     }
+
+     body {
+         padding: 1em;
+         margin: auto;
+     }
+
+     @media only all and (pointer: coarse), (pointer: none) {
+         body {
+             font-size: 5.5vmin;
+         }
+     }
+
+     @media only all and (pointer: fine) {
+         body {
+             font-size: calc(16px + 0.6vmin);
+             min-width: 500px;
+             max-width: 50em;
+         }
+     }
+    </style>
+
+    <body>
+        <div style="display: flex; flex-direction: horizontal;">
+            <a href="index.html">Home</a>
+            <span style="margin-left: 1em; margin-right: 1em;">|</span>
+            <a href="feed.xml">RSS Feed</a>
+        </div>
+        <h1>Blog</h1>
+'
+}
+
+print-blog-html-bottom() {
+    echo '    </body>
+    </html>'
+}
+
+# Note: pubDate and lastBuildDate are both set to the current time.
+print-blog-rss-top() {
+    cat <<EOF
+<?xml version="1.0"?>
+<rss version="2.0">
+   <channel>
+      <title>Hugot Blog</title>
+      <link>https://hugot.nl/blog.html</link>
+      <description>Hugo's personal blog</description>
+      <language>en-us</language>
+      <pubDate>$(date)</pubDate>
+      <lastBuildDate>$(date)</lastBuildDate>
+      <docs>http://blogs.law.harvard.edu/tech/rss</docs>
+      <generator>Hugo's Custom Bash Script</generator>
+      <managingEditor>social@hugot.nl</managingEditor>
+      <webMaster>infra@hugot.nl</webMaster>
+EOF
+}
+
+print-blog-rss-bottom() {
+    echo '</channel>
+</rss>'
+}
+
+el() {
+    format_string="$1"
+    shift
+
+    printf "<$format_string>" "$@"
+}
+
+el-close() {
+    echo "</$1>"
+}
+
+el-enclose() {
+    element_name="$1"
+    shift
+
+    printf '%s' "<$element_name>"
+    printf '%s' "$@"
+    printf '%s' "</$element_name>"
+}
+
+site_url="https://hugot.nl"
+
+blog_html="$here/blog.html"
+new_html="$blog_html.new"
+
+blog_rss="$here/feed.xml"
+new_rss="$blog_rss.new"
+
+print-blog-html-top > "$new_html"
+print-blog-rss-top > "$new_rss"
+
+while read -r post_html; do
+    # Convert the post's html to text to make it easier to use the blog's text
+    text="$(html-to-text "$post_html" | escape-html)" || exit $?
+
+    # The title should be on the 2nd line of text, right after the link to the
+    # homepage. This is a bit inflexible but it will do for now.
+    title="$(tail -n +2 <<<"$text" | head -n 1 | tr -d '*')" || exit $?
+
+    # Use the first 5 lines after the title as post excerpt.
+    excerpt="$(tail -n +3 <<<"$text" | head -n 5)" || exit $?
+ 
+     # Escape the post html file name to safely use it in the generated html.
+     href="$(escape-html <<<"$post_html")" || exit $?
+ 
+     post_dir="$(dirname "$post_html")" || exit $?
+     pubdate_file="$post_dir/publish_date.txt"
+ 
+     # Determine a publishing date for the post
+     if [[ -f "$pubdate_file" ]]; then
+         read -r pubdate < "$pubdate_file"
+     else
+         pubdate="$(date)"
+         echo "$pubdate" > "$pubdate_file"
+     fi
+ 
+     {
+         el div
+ 
+         el 'a href="%s"' "$href"
+         printf '<h2 style="margin-bottom: 0.1em;">%s</h2>' "$title"
+         el-close a
+ 
+         printf '<i style="font-size: 0.8em;">%s</i>' "$pubdate"
+ 
+         el 'p style="margin-top: 0.5em;"'
+         printf '%s ... <a href="%s">Continue reading</a>' "$excerpt" "$href"
+         el-close p
+ 
+         el-close div
+ 
+         el hr
+     } >> "$new_html"
+ 
+     {
+         el item
+         el-enclose title "$title"
+         el-enclose link "$site_url/$href"
+         el-enclose description "$excerpt"
+         el-enclose pubDate "$pubdate"
+ 
+         echo "<guid isPermaLink=\"false\">$title$(base64 <(cksum <<<"$text"))</guid>"
+ 
+         el-close item
+     } >> "$new_rss"
+ done < "$posts_file"
+ 
+ print-blog-html-bottom >> "$new_html"
+ print-blog-rss-bottom >> "$new_rss"
+ 
+ mv -v "$new_html" "$blog_html" || exit $?
+ mv -v "$new_rss" "$blog_rss" || exit $?
+ 
+ echo 'SUCCESS!'
+
+ + diff --git a/posts.txt b/posts.txt index 38ed378..4958a3e 100644 --- a/posts.txt +++ b/posts.txt @@ -1 +1,2 @@ +posts/simple-static-blog/index.html posts/introduction/index.html diff --git a/posts/simple-static-blog/index.html b/posts/simple-static-blog/index.html new file mode 100644 index 0000000..2ead911 --- /dev/null +++ b/posts/simple-static-blog/index.html @@ -0,0 +1,205 @@ + + + + Creating a Simple Static Blog + + + + + + + Home +

Creating a Simple Static Blog

+ +

+ I love personal websites. It's amazing that people can share content with the + entire world just by writing some text and throwing it behind a web server. I + wanted to know what that is like, so I set out to create a personal website of + my own. As you can see I succeeded in the end. But getting here wasn't as + straight forward as I initially thought it would be. I thought that, being a + programmer and knowing a thing or two about web servers, setting up my own + website was going to be easy: How complicated can it be to throw some text + behind a web server, right?! I was wrong. Throwing text behind a web server can be + very complicated (and wasteful). But it doesn't have to be! +

+ +

The search for a CMS

+

+ The first thought that popped into my head when I got started was: I need to + find myself a CMS. I had a few requirements: my site should be + self-hosted, be lightweight, have no JavaScript in it and it should look + pretty. I also wanted to be able to write blog posts in markdown using my + trusty text editor. The first CMSes that came to mind were WordPress, Ghost, + Jekyll and Hugo. I don't want to get into too much detail, so I'll summarize + my judgments here without any nuance: Wordpress is the devil, Ghost is great + but too bulky and both Jekyll and Hugo required me to learn about theming and + project structure which I deemed too much effort. I just wanted to write some + text and throw it behind a web server, but all solutions I saw were sophisticated + programs that were designed to "scale", support "modern + workflows" or be "easy to use with integrated WYSIWYG + editors". I didn't feel like exploring the idea further and gave up on + having a website for a while. +

+ +

+ Then, a few months back, I learned about writefreely. Writefreely is an open + source web application from write.as that lets users create blogs that + federate through the fediverse. I had just started to become acquainted with + the fediverse and it seemed like a cool idea to me at the time, so me and a + friend decided to set up our own instance. It wasn't too hard to set up and + once it was running I only needed a couple of hours to add some custom + style sheets. I finally had a fully functioning blog that satisfied all of my + needs! +

+ +

+ After that the holiday season came along and I turned my back on blogging for + a while. When I checked on our instance three or four weeks later I was + displeased to discover that spammers had created accounts on the instance and + were posting spammy garbage. Sure, we could just close registrations. But this + event reminded me that hosting any dynamic web application on the public + internet is a big responsibility that involves keeping software up to date, + monitoring and doing other configuration/maintenance work. Not to mention + having to do regular database backups. I didn't feel like having to do any of + that, I already have by hands full with self-hosting a bunch of other + services. Once again I had found a complicated solution for a simple problem: + I just wanted to throw some text behind a web server, remember? Why did I need to use a CMS + again? +

+ +

+ CMSes seem to offer solutions to a problem that I don't have: I don't mind + writing plain html and I most certainly don't need a WISYWIG editor. I also + don't need plugins, dynamic code for analytics, pretty yaml or toml + configuration files, templates, extensive theming, admin panels, markdown, + mailing lists, comment threads or any other common CMS features. I just want + to throw some text behind a web server, so why not just write some HTML and do + exactly that? +

+ +

A CMS in ~200 lines

+

+ It was decided: I was going to blog in plain HTML. Having figured out what I + actually wanted, I went to work. The first order of business was creating a + style sheet to make things look good. I made it my goal to use as little CSS + as possible and I managed to limit myself to just these 23 lines: +

+ + + +
+
+html {
+    font-family: Helvetica, Arial, sans-serif;
+    color: #5b4636;
+    background-color: #f4ecd8;
+}
+ 
+body {
+    padding: 1em;
+    margin: auto;
+}
+ 
+@media only all and (pointer: coarse), (pointer: none) {
+    body {
+        font-size: 5.5vmin;
+    }
+}
+ 
+@media only all and (pointer: fine) {
+    body {
+        font-size: calc(16px + 0.6vmin);
+        min-width: 500px;
+        max-width: 50em;
+    }
+}
+            
+
+ +

+ This is all the CSS I need to have a responsive website that looks pretty (I + stole the colors from firefox's reader mode btw). It's such a small amount + that I don't mind copy-pasting it at the top of all new HTML pages that I add + to my website. This might make it harder to change the styling later, but it + has the added benefit that each page is a standalone document. So for example wget PAGE_URL + will download a HTML page that looks exactly the same locally as it does on + the web without having to download any extra assets. +

+ +

+ The next challenge was creating and maintaining the article listing page and + the RSS feed for the blog. I don't mind typing HTML pages, but typing out a + page and an RSS feed containing excerpts/titles from other files gets old soon + and I'd be bound to forget updating its content every once in a while. This + seemed like a perfect occasion to write a little bash script, so I did. You + can find the script here (raw) and + here (pretty). What it basically + does is read in a file called posts.txt that has html filenames in it, + separated by newlines. Using those filenames and the contents of the files it + then generates a HTML page (called blog.html) + and an RSS feed (called feed.xml). +

+ +

+ I keep all of this neatly stored under version control + here, so deploying a new version + is as easy as running git pull on my web server. I can honestly say that + this is the simplest, most user-friendly CMS that I have ever used, and it + only took me several months to figure out that this is exactly what I needed 🤓. +

+ +

+ So, to conclude this story: websites are just HTML. You don't need fancy + programs or WYSIWYG editors to create a website. Just a text editor, a web + server and some spare time. +

+ + diff --git a/posts/simple-static-blog/publish_date.txt b/posts/simple-static-blog/publish_date.txt new file mode 100644 index 0000000..5071fa2 --- /dev/null +++ b/posts/simple-static-blog/publish_date.txt @@ -0,0 +1 @@ +Sat 08 Feb 2020 12:14:16 PM CET