diff --git a/blog.html b/blog.html index ddff6af..5a986d5 100644 --- a/blog.html +++ b/blog.html @@ -39,7 +39,14 @@
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
+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
+ 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 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?
+
+ 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:
+
+ 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
+ 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
+ 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.
+
+#!/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/&/\&/g; s/</\</g; s/>/\>/g; s/"/\"/g; s/'"'"'/\'/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
+
+ The search for a CMS
+ A CMS in ~200 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;
+ }
+}
+
+ 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.
+ 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 🤓.
+