1
0
Fork 0

Compare commits

..

7 Commits

Author SHA1 Message Date
Tim Van Baak 7aef7edf19 Add an initial blog post 2023-09-28 15:42:16 -07:00
Tim Van Baak cf99106e30 Remove preview images
Relative URLs appear to be broken and would require adding a manual patch step using pagefind's facility for that
2023-09-28 15:42:16 -07:00
Tim Van Baak 4bf6252ed1 Add RSS feed functionality 2023-09-28 15:42:16 -07:00
Tim Van Baak 0c1caf26d2 Build to publish in a separate path 2023-09-28 15:42:16 -07:00
Tim Van Baak f1eb82cf0b Switch from entr to inotifywait 2023-09-28 15:42:16 -07:00
Tim Van Baak 4d79307fe1 Start a blog folder 2023-09-28 15:42:15 -07:00
Tim Van Baak 26502786af Expose python env as a package
This allows building the env into the local workspace, making it easier to configure VS Code to point to it
2023-09-28 15:42:15 -07:00
10 changed files with 93 additions and 13 deletions

2
.gitignore vendored
View File

@ -1 +1,3 @@
out/ out/
srv/
venv

View File

@ -1,17 +1,23 @@
.PHONY: * .PHONY: *
build: build:
./build.py ./build.py out/
pagefind --site out/ pagefind --site out/
clean: clean:
test -e out && rm -rf out test -e out && rm -rf out || true
test -e srv && rm -rf srv || true
watch: watch:
while sleep 1; do find src/ build.py Makefile | entr -d make build; done while inotifywait -r -e modify -e move -e create -e delete build.py Makefile src/; do make build; done
serve: serve:
python -m http.server --directory out/ python -m http.server --directory out/
publish: pubdate:
rsync -av out/* ssh.alogoulogoi.com:/srv/www.alogoulogoi.com sed -i "s/pubdate: now/pubdate: $$(date -Isec)/" src/blog/**/*.md
upload:
./build.py srv/
pagefind --site srv/
rsync -av srv/* ssh.alogoulogoi.com:/srv/www.alogoulogoi.com

View File

@ -1,27 +1,32 @@
#!/usr/bin/env python #!/usr/bin/env python
import argparse import argparse
from datetime import datetime, timezone
import copy import copy
import os import os
import pathlib import pathlib
import shutil import shutil
import bs4 import bs4
from feedgen.feed import FeedGenerator
import markdown import markdown
def main(): def main():
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument("src", help="source directory", nargs="?", default="./src") parser.add_argument("out", help="output directory")
parser.add_argument("out", help="output directory", nargs="?", default="./out")
args = parser.parse_args() args = parser.parse_args()
src = pathlib.Path(args.src) src = pathlib.Path("src")
out = pathlib.Path(args.out) out = pathlib.Path(args.out)
md = markdown.Markdown(extensions=["attr_list", "footnotes", "md_in_html", "meta"]) md = markdown.Markdown(extensions=["attr_list", "footnotes", "md_in_html", "meta"])
comment_md = markdown.Markdown() comment_md = markdown.Markdown()
# Map of feed url -> FeedGenerator object
feeds = {}
build_date = datetime.now(timezone.utc)
# Load the template # Load the template
template = bs4.BeautifulSoup( template = bs4.BeautifulSoup(
(src / ".template.html").read_text(encoding="utf8"), (src / ".template.html").read_text(encoding="utf8"),
@ -108,10 +113,41 @@ def main():
aside.extend(html.p.contents) aside.extend(html.p.contents)
page.header.append(aside) page.header.append(aside)
# RSS metadata
if "feed" in meta and "pubdate" in meta:
pubdate = datetime.fromisoformat(meta["pubdate"][0])
link = f"https://www.alogoulogoi.com/{dest.relative_to(out).as_posix()}"
for feed in meta["feed"]:
if feed not in feeds:
feeds[feed] = []
feeds[feed].append({
"title": meta_title[0],
"link": link,
"description": "",
"pubdate": pubdate,
})
# Write the fully templated page # Write the fully templated page
print("Writing ", dest) print("Writing ", dest)
dest.write_text(str(page)) dest.write_text(str(page))
for feed, items in feeds.items():
fg = FeedGenerator()
fg.title(f"alogoulogoi /{feed}/")
fg.link(href=f"https://www.alogoulogoi.com/{feed}/feed.xml")
fg.description("Blog posts from alogoulogoi")
fg.language("en-us")
fg.lastBuildDate(build_date)
for item in sorted(items, key=lambda i: i["pubdate"]):
entry = fg.add_entry()
entry.title(item["title"])
entry.link(href=item["link"])
entry.description(item["description"])
entry.published(item["pubdate"])
rss_path = (out / feed / "feed.xml")
os.makedirs(rss_path.parent, exist_ok=True)
rss_path.write_bytes(fg.rss_str(pretty=True))
print("Processed", count, "files") print("Processed", count, "files")

View File

@ -17,13 +17,18 @@
pyenv = pkgs.python3.withPackages (pypkgs: [ pyenv = pkgs.python3.withPackages (pypkgs: [
pypkgs.markdown pypkgs.markdown
pypkgs.beautifulsoup4 pypkgs.beautifulsoup4
pypkgs.feedgen
]); ]);
in { in {
packages.${system} = {
inherit pyenv;
};
devShells.${system} = { devShells.${system} = {
default = pkgs.mkShell { default = pkgs.mkShell {
packages = [ packages = [
pyenv pyenv
pkgs.entr pkgs.inotify-tools
pkgs.rsync pkgs.rsync
pkgs.pagefind pkgs.pagefind
]; ];

View File

@ -8,7 +8,7 @@ I self-host a Gitea instance at [git.alogoulogoi.com](https://git.alogoulogoi.co
# Colophon # Colophon
**Technology:** This website is built from [Markdown and HTML sources](https://git.alogoulogoi.com/Jaculabilis/www) using [Python-Markdown](https://python-markdown.github.io/). It is hosted on a NixOS VPS running Nginx and serving static files deployed via `rsync`. This website is built from [Markdown and HTML sources](https://git.alogoulogoi.com/Jaculabilis/www) using [Python-Markdown](https://python-markdown.github.io/). The static files are deployed to a NixOS VPS via `rsync` and served by Nginx.
Before the Internet was a deployment system for JavaScript, it was a web of interlinked hypertext documents. This site's design reflects that forgotten dream. The pages are self-contained, the styling is minimal, and the content is accessible without scripting enabled. Before the Internet was a deployment system for JavaScript, it was a web of interlinked hypertext documents. This site's design reflects that forgotten dream. The pages are self-contained, the styling is minimal, and the content is accessible without scripting enabled.
@ -17,5 +17,3 @@ A selection of other sites used as design inspiration:
* [brutalist-web.design](https://brutalist-web.design/) * [brutalist-web.design](https://brutalist-web.design/)
* [blog.aqwari.net](https://blog.aqwari.net/) * [blog.aqwari.net](https://blog.aqwari.net/)
* [spectrum-os.org](https://spectrum-os.org/) * [spectrum-os.org](https://spectrum-os.org/)
**Privacy:** Nginx keeps request logs, but I never check them. I don't know what I'd do with them, either.

View File

@ -0,0 +1,23 @@
---
title: The traditional first software engineer blog post
pubdate: 2023-09-28T15:39:59-07:00
feed: blog
---
It seems appropriate for a first post on a blog to explain why the blog exists and how it is built. For people other than software engineers, the latter question is typically not very interesting because the blog is on a blogging site like WordPress or built with a CMS like WordPress. Software engineers, however, have a habit of doing everything from scratch, so they also explain their hosting choice, Emacs plugins, operating system version, and WordPress deployment.
I do not have a profound answer to either question, so this will be short. I set up this website and this blog to be able to put things on the public Internet and share them with people. Some of those things might not have a particular audience. Someone, somewhere, said something to the effect that teaching something is the best way to learn it. Having to explain something to other people helps solidify your understanding as you are forced to articulate things you had only nebulously grasped before. If I write about how I solved some problem or used some tool, that might also help someone else in the same situation. People learn things differently and sometimes all you need is to see the information presented in the way that clicks for you.
The explanation of how the blog is built is similarly simple. A directory tree of markup text is parsed by a Python build script into lean HTML and written out to a destination directory tree, which is then uploaded to the server where the files are served. It'd be nice if I could say I used this project to learn a new technology or language, but none of the tools here are new to me. I would defend this decision by saying that I [chose boring technology](https://mcfunley.com/choose-boring-technology), but the reason to choose boring technology is to save your "innovation tokens" for the innovative technology your company is building. A static site and a blog are not innovative, so they do not benefit from token austerity.
Perhaps this explains the tendency of personal software blogs to sit atop overengineered tech stacks: setting up a blog does not interest the tinkerer unless there is something technologically interesting involved. I don't know if "technologically interesting" is always a virtue; "may you live in interesting times" is considered a curse. I don't want to go down a path where "debugging my blog" could describe my weekend.
With that said, here are some things I *did* use for the first time while building this:
* [Python-Markdown](https://python-markdown.github.io/), which has some built-in extensions and supports inline HTML. That lets me do things like insert short page-specific `<script>` or `<style>` blocks.
* [python-feedgen](https://feedgen.kiesow.be/), which generates the RSS feeds for this blog.
* [pagefind](https://pagefind.app/), which makes a static site searchable without requiring a backend. Neat!
* [inotifywait](https://linux.die.net/man/1/inotifywait), which I use to rebuild the site while I develop it. Responsive rebuilds are nothing new in the current year, but it's not complicated to use it in your own shell workflows.
* [Applying patches to nixpkgs on import.](https://git.alogoulogoi.com/Jaculabilis/www/commit/75a860a95ad3ea63b53878e5e378403816fd6b9f) I found pagefind while it was still in PR to nixpkgs, and I try to keep my flakes on NixOS releases so I don't have to re-download the entire Linux userspace for every project. Patching it in let me just build it from source instead of having to pull in `nixpkgs-unstable`. I had to include another change not from the PR to get the diff to apply correctly. The PR's merged now, so this only needs to work until 23.11 is released and I upgrade things.
I considered using [Hugo](https://gohugo.io/), but it seemed like it had a lot more control knobs than I needed, and I would need to learn how to create a theme before I could make a website as minimalist as I wanted. If I end up needing more features for page generation, I might reconsider using it or a similar tool, but I don't think there's a lot of marginal value in that right now.

1
src/blog/2023/index.md Normal file
View File

@ -0,0 +1 @@
* [The traditional first software engineer blog post](./blog-start.md)

7
src/blog/index.md Normal file
View File

@ -0,0 +1,7 @@
---
title: Blog
---
[RSS](./feed.xml)
* [The traditional first software engineer blog post](./2023/blog-start.md)

View File

@ -6,6 +6,8 @@ title: Home
=> [Projects I've worked on](./project/). => [Projects I've worked on](./project/).
=> [Blog posts](./blog/).
=> [About this site](./about/). => [About this site](./about/).
=> [Search this site](./search/). => [Search this site](./search/).

View File

@ -9,6 +9,6 @@ Search results generated by [Pagefind](https://pagefind.app/).
<div id="search"></div> <div id="search"></div>
<script> <script>
window.addEventListener('DOMContentLoaded', (event) => { window.addEventListener('DOMContentLoaded', (event) => {
new PagefindUI({ element: "#search", showSubResults: true }); new PagefindUI({ element: "#search", showSubResults: true, showImages: false });
}); });
</script> </script>