start reading

starbreaker.org button


Reset

Here we go again. I might actually redo this site again this month.


Short version for webmasters: Please update all links to existing posts on starbreaker.org to point to old.starbreaker.org. I will be breaking things soon.


I never got as far as I wanted in remaking this website. My day job got in the way. Not to mention my dependency on tools like pandoc, Markdown, and Org Mode. Use of the latter two necessitate use of the former, which converts these formats into HTML. However, even with parallel execution in GNU make on an eight-core CPU with at least 8GB of RAM, building this site is slower than I’d like with over 200 posts. Admittedly, it doesn’t help that I have a few novels on this website as well.

Does it really matter that building this website currently takes about two minutes? Perhaps not, since make supports incremental builds. Nevertheless, I don’t want to take a full build to take that long. Nor did I want to remain dependent on pandoc, since that tool was the bottle-neck.

I could have switched to Hugo, but that’s an extremely opinionated system. Worse, it’s documentation is such that bloggers have had to write their own getting started guides. In fairness, if the need for bloggers to write how-to posts is a demerit against a given technology, then the likes of GNU/Linux, GNU Emacs, FreeBSD, vim, OpenBSD, etc. would be irredeemable. Nevertheless, the whole point of me figuring out how to build a website with make, shell scripts, and tools like HTML-XML-utils was to avoid dependency on a static site generator that had its developers opinions on how to build a website baked in. This isn’t Burger King. If you want to have it your way, you’ve got to do it yourself.

It didn’t help that I had been reading Patterns for Personal Web Sites by Mark L. Irons, either. There’s a lot that still makes sense today, over twenty years after he last updated it. Nevertheless, I’ve come to think that Patterns is best read as a collection of observations rather than a coherent set of recommendations or a guide to website design.

For a while I had been experimenting with using shell scripts for static site generation. Each page or post had a .htm file containing markup and an executable .sh file containing metadata as shell variables. One of these variables specified the layout, which was another shell script. For example, here’s the article.sh layout.

#!/usr/bin/env bash

PAGE_CONTENT=$(cat "${1}")

cat <<EOF
<!-- include "hello.html" -->
<!doctype html>
<html lang="_LANG" itemscope itemtype="https://schema.org/_SCHEMA_TYPE">
    <head>
        <!-- include "head.html" -->
        <!-- include "head-level-_LEVEL.html" -->
    </head>
    <body id="starbreaker-org">
        <!-- include "header.html" -->
        <hr>
        <article id="content">
            ${PAGE_CONTENT}
            <!-- include "replies-welcome.html" -->
        </article>
        <hr>
        <nav id="breadcrumbs-bottom" class="breadcrumbs no-print" aria-label="breadcrumbs at the bottom of the page">
            <!-- include "_BREADCRUMB" -->
        </nav>
        <!-- include "sitenav-level-_LEVEL.html" -->
        <hr>
        <!-- include "footer-level-_LEVEL.html" -->
    </body>
</html>
<!-- include "fuck-AI.html" -->
EOF

I’d process all of this using another shell script called to-html.sh, which looked like this.

#!/usr/bin/env bash

INPUT=$1
OUTPUT=$2

# shellcheck source=settings.sh
. "./settings.sh"
. "${INPUT/.htm/.sh}"

PAGE_SCHEMA_TYPE="${PAGE_TYPE/website/WebSite}"
PAGE_SCHEMA_TYPE="${PAGE_TYPE/blogpost/BlogPosting}"
PAGE_CREATED_TIMESTAMP=$("${DATE}" -Iseconds -d "${PAGE_CREATED}")
PAGE_CREATED_DISPLAY=$("${DATE}" -d "${PAGE_CREATED}" +"%a, %d %b %Y")
PAGE_UPDATED_TIMESTAMP=$("${DATE}" -Iseconds -d "${PAGE_UPDATED}")
PAGE_UPDATED_DISPLAY=$("${DATE}" -d "${PAGE_UPDATED}" +"%a, %d %b %Y")
PAGE_BASENAME=$(basename "${OUTPUT}")

if [ -z "$PAGE_META_TITLE" ]
then
    PAGE_META_TITLE="${PAGE_TITLE}"
fi

"${PAGE_LAYOUT}" "${INPUT}" "${PAGE_TSV}" | \
    sed -e "s|_LEVEL|${PAGE_LEVEL}|g" \
        -e "s|_BREADCRUMB|${PAGE_BREADCRUMB}|g" | \
    hxincl -b ./partials/ -x | \
    hxtoc -x -t -l 2 | \
    sed -e "s|_SITE|${SITE}|g" \
        -e "s|_META_TITLE|${PAGE_META_TITLE}|g" \
        -e "s|_TITLE|${PAGE_TITLE}|g" \
        -e "s|_DESCRIPTION|${PAGE_DESCRIPTION}|g" \
        -e "s|_KEYWORDS|${PAGE_KEYWORDS}|g" \
        -e "s|_LANG|${PAGE_LANG}|g" \
        -e "s|_LOCALE|${PAGE_LOCALE}|g" \
        -e "s|_MASTODON|${MASTODON}|g" \
        -e "s|_PIXELFED|${PIXELFED}|g" \
        -e "s|_FRIENDICA|${FRIENDICA}|g" \
        -e "s|_BADREADS|${BADREADS}|g" \
        -e "s|_EMAIL|${EMAIL}|g" \
        -e "s|_OPERATOR|${OPERATOR}|g" \
        -e "s|_CREATED_TIMESTAMP|${PAGE_CREATED_TIMESTAMP}|g" \
        -e "s|_CREATED_DISPLAY|${PAGE_CREATED_DISPLAY}|g" \
        -e "s|_UPDATED_TIMESTAMP|${PAGE_UPDATED_TIMESTAMP}|g" \
        -e "s|_UPDATED_DISPLAY|${PAGE_UPDATED_DISPLAY}|g" \
        -e "s|_CREATED|${PAGE_CREATED}|g" \
        -e "s|_UPDATED|${PAGE_UPDATED}|g" \
        -e "s|_RELATIVE_URL|${OUTPUT/site/}|g" \
        -e "s|_CANONICAL_URL|${DOMAIN}${OUTPUT/site/}|g" \
        -e "s|_BASENAME|${PAGE_BASENAME}|g" \
        -e "s|_PREVIEW_IMAGE_WIDTH|${PREVIEW_IMAGE_WIDTH}|g" \
        -e "s|_PREVIEW_IMAGE_HEIGHT|${PREVIEW_IMAGE_HEIGHT}|g" \
        -e "s|_PREVIEW_IMAGE_TYPE|${PREVIEW_IMAGE_TYPE}|g" \
        -e "s|_PREVIEW_ALT_TEXT|${PREVIEW_IMAGE_TYPE}|g" \
        -e "s|_PREVIEW_IMAGE|${PREVIEW_IMAGE}|g" \
        -e "s|_SCHEMA_TYPE|${PAGE_SCHEMA_TYPE}|g" \
        -e "s|_TYPE|${PAGE_TYPE}|g" \
        -e "s|_ICBM_LATITUDE|${ICBM_LATITUDE}|g" \
        -e "s|_ICBM_LONGITUDE|${ICBM_LONGITUDE}|g" \
        -e "s|_DOMAIN|${DOMAIN}|g" \
        -e "s|_YEAR|${YEAR}|g" > "${OUTPUT}"

This might seem incredibly gnarly, and it probably is. However, a full build only took about 15 seconds with over 200 posts and several novels running over 50,000 words. Nevertheless, this still wasn’t good enough. I didn’t want to make a full-on static site generator, even if it was built from shell scripts.

I hit upon a happier medium when building a less salty and non-Oedipal altenative to Motherfucking Website called Actual Website. I have a template that I copy when creating a new page. I fill out part of the template using my editor’s find/replace functions. The rest is filled out with a shell script. I handle partials with hxincl and generate a table of contents with hxtoc.1

Nor did I want to continue running starbreaker.org as I had been. Right now this is an everything/nothing site. I write about everything here, where “everything” is whatever I’m into at the time. However, this lack of focus is crowding out the fiction I want to write.

I also have multiple domains, of which starbreaker.org is but one. They cost relatively little to rent per year; each costs less to register for a year than it costs my wife and me to go out for pizza on a Friday night.2

Here’s what I’m thinking of doing. First: this site in its current form, with this post, is getting mirrored to old.starbreaker.org. This domain will remain up until at least January 1, 2025.

Next, I will be building websites at the following domains, for the following purposes.

starbreaker.org
this site, but exclusively for my science fantasy saga
matthewgraybosch.com
a professional site and technical blog
matthewgraybosch.org
a SFW personal site and artistic/emotional blog
actualwebsite.org
advocacy for personal websites and appropriate technology in web design
other unnamed websites
for stuff I’d only want to publish under a pseudonym because it might offend censorious conservatives, my trade3 still isn’t unionized, I live in an at-will employment state 4.

Why would I do this? People who are interested in my fiction aren’t necessarily interested in my tinkering. People interested in my tinkering aren’t necessarily interested me in my blogging about old heavy metal albums. People here for any of the above probably don’t want my rants about how the Republican Party is basically the Ku Klux Klan but without the white hoods. And if somebody does want all of these, it shouldn’t be that hard for them to subscribe to each website’s RSS feed.

How will I get there? I start, I’ll rebuild the other sites first, and move stuff from here to there. Where applicable I should be able to set up HTTP redirects easily enough, which should avoid breaking links from other websites. Once that’s done, it will be time to revamp this website.

Watch this space. Among other things, I want to break up my longer fiction so that I’m not pushing entire novels in a single HTML file and serialize it via RSS.5 I’d also like to create a knowledge base of sorts for characters, organizations, monsters, etc. within the fiction.

Will you be there? You’re welcome to stick around. But if not, I’ll understand and continue without you.

notes


  1. These are both part of HTML-XML-utils, which is maintained by the W3C. If you’re on some kind of Unix, you can install it with your package mangler. hxincl is like having a limited form of Apache’s Server-Side Includes on localhost. It’s also more convenient than having to learn PHP. I used to know PHP, but that was several years (and major versions) ago. I’d rather not re-learn it unless I’m getting paid.↩︎

  2. I do most of the cooking, but sometimes I don’t feel like it and neither does she. So she suggests we go out for pizza. I usually agree, because we know a good place and I’m basically a cheap date. If she wanted to eat somewhere fancier, we would. Not like I can’t afford it every once in a while.↩︎

  3. Yes, I think software developers, sysadmins, and other IT workers should have a trade union. Admittedly, we might be more like writers or actors than truck drivers or factory workers. Nevertheless, screenwriters are unionized via the Writers’ Guild of America, and actors have SAG-AFTRA. We techies are long overdue for something similar.↩︎

  4. The First Amendment isn’t the shield against oppression some free-speech absolutists insist it is. The original Amendment only says that Congress shall make no law abridging freedom of speech. It took the Fourteenth Amendment’s “Equal Protection” clause to apply that prohibition to state and local governments. No constitutional precedent or legal precedent guarantees First Amendment protections on the job. Students might have Tinker v. Des Moines, but workers have nothing unless they’re unionized.↩︎

  5. The fact that I can doesn’t make it a good idea.↩︎