The Bajoran Engineer Community Engineering This week 39
This week: a site rebuild, a keynote turned essay, and three small gotchas
Wagtail 8 and a build-free frontend for this site, Part 1 of my Boldly Go series, a Django 6.1 upgrade for Wildflower Software, and three bugs worth knowing about.
I build a lot more than I write about, so I'm trying something new: a short weekly roundup of what I worked on and what I learned. A lot of this week happened in conversation with Claude, which turns out to be a good rubber duck that also reads the release notes.
Key takeaways
- dawnwages.info is on Wagtail 8 and no longer needs a frontend build.
- Part 1 of Boldly Go, my series based on my DjangoCon US keynote, is published.
- Wildflower Software's site moved from Python 3.9 and Django 4.2 to Python 3.14 and Django 6.1.
- Three gotchas: Wagtail
StructValuelookups in templates,*.localhostover IPv6, and zsh word splitting.
#This site got a rebuild
Most of my week went here. The site now runs on Wagtail 8. Puput, the blog engine I use, didn't allow Wagtail 8 yet, so I'm running a fork that loosens the version pin. I'd like to get that change upstream.
I also dropped the frontend build completely. There's no Node and no npm, just plain CSS and JavaScript served through Django's static files, with WhiteNoise handling hashed filenames and compression. The thing I learned: nesting, custom properties, @layer and container queries all work in current browsers, and that removes most of the reasons I ever reached for Sass. For a content site, as little build tooling as possible is the right default in 2026.
Then the part I enjoyed most. I went through every page looking for anything that read as AI-generated, and rewrote it:
- Résumé-style copy ("Owned…", "Unified…") became first person, the way I actually write.
- An emoji on every card, a spinning ring around my photo, and pill shapes everywhere all went. Pills now only appear on blog tags and categories, where they mean something.
- The accent color is a deeper indigo, checked against WCAG AA contrast on every page.
New on the site:
- A speaker rider that says what I value in a conference: equity, access, and supporting speakers from underrepresented groups.
- A redesigned Talks and Podcasts page with video links for past talks.
- A Ko-fi link, for anyone who wants to support the community work that doesn't come with a paycheck.
- A note on the home page when there's a new post from the past week. That might be how you found this one.
- Blocks for technical posts: anchored section headings, code with filenames, terminal sessions, callouts and TL;DR lists. This post uses a few of them.
#From keynote to essays: Boldly Go
My DjangoCon US 2026 keynote, Boldly Go, Building Worlds, is turning into a three-part series. Part 1 is up: What Octavia Butler's Notebook Knew About Self-Efficacy. It's about Butler writing her audacious goals on paper, and what open source communities owe the people who are just starting out. Part 2 covers agency, context, experimentation and crew as the parts of being a builder. Part 3 compares agency in human development with "agency" in AI agent software.
Two more things I learned while editing. First, my early drafts were too self-effacing. The rewrite leads with the research and uses my own story as evidence, not confession. Second, title cards mostly matter for how a link looks when it's shared. Readers skip decorative images on the page. I made cards from NASA and ESA Webb images. ESA/Webb images are licensed CC BY 4.0, so each card and post carries a credit.
#Wildflower Software, upgraded
The Wildflower Software site went from Python 3.9, which reached end of life in October 2025, and Django 4.2 to Python 3.14.7 and Django 6.1.1. Django 6.1 needs Python 3.12 or newer, so the Python jump wasn't optional. We read the 6.0 and 6.1 release notes and checked every breaking change against the code before touching anything, and all 63 tests pass. The one real change was email: Django 6.1 configures it through a new MAILERS setting and deprecates the old one, so we moved to it now rather than wait for 7.0 to break it.
I also rewrote the README and ran every command in it from a clean copy of the repo. A setup guide with commands that don't work is worse than no guide.
#Three small gotchas
#1. Wagtail StructValue hides methods from templates
My section headings were rendering with id="". The block had an anchor() method that builds a slug, but it also had a field called anchor. A StructValue is a dict, and Django templates try a dictionary lookup before an attribute lookup. So {{ value.anchor }} returned the empty field and never called the method. The fix is a property with a name that isn't a field:
class SectionHeadingValue(blocks.StructValue):
def anchor(self):
return slugify(self.get("anchor") or self.get("text"))
@property
def anchor_id(self):
# {{ value.anchor }} resolves to the raw "anchor" field,
# so templates use {{ value.anchor_id }} instead.
return self.anchor()
#2. labs.localhost works in curl but not in the browser
The Wildflower site serves a second site on a subdomain, and labs.localhost:8042 refused to load in the browser while curl was fine. It wasn't DNS: macOS already resolves *.localhost. The name resolves to both ::1 and 127.0.0.1, browsers try IPv6 first, and runserver only listens on IPv4. Chrome falls back for plain localhost, but not for subdomains. Binding the dev server to IPv6 as well fixes it:
python manage.py runserver "[::]:8042"
#3. zsh doesn't split unquoted variables
This one caused trouble twice this week. In bash, cmd $args splits $args into words. zsh doesn't, so args="--only 1" reaches your script as one argument. It looks exactly like a bug in the script you're testing. Use an array, or ${=args} to split on purpose.
#Workflows I'm building
- A news brief for writing. It pulls from a set of feeds, ranks stories by how well they fit what I write about, and checks each one against its primary source before suggesting an angle. Lesson learned: keep reference tooling like this out of your product repos.
- Write once, publish everywhere. Tags on a post decide where it goes: my blogs, Substack and LinkedIn. Some platforms don't offer a publishing API, so not every destination can be fully automatic.
- A design system for Wildflower Software. The site's colors and type become stream overlays first, and business cards later.
#Next week
Parts 2 and 3 of Boldly Go, and getting the Puput fork upstream. If any of this is useful to you, or you've hit the same gotchas, I'd love to hear about it.
If this post helped, you can support my open source work on Ko-fi.