I wrote an Architecture Decision Record to Use SVGs for icons for Lullabot along with some of my wonderful co-owners. I’m so happy this is not at all controversial in 2024.

My brilliant co-owner Greg Dunlap has a Kickstarter up for his new book, Designing Content Authoring Experiences. If you work with Content Management Systems, you owe yourself a look.

I setup a local LLM integration in Neovim via ollama.nvim, and it works well. Now the big question: will it actually be useful?

Here’s my contribution to the “what apps am I using?” posts.

NEDCamp is great, as always.

I wrote a blog post for Lullabot on Useful git configurations you may have missed.

From Sannie Lee, writing about the value of a liberal arts education in tech.

Whether it was a history or literature class, one common thread across all my courses was thinking critically. Looking at historical events or understanding the meaning in a novel, I learned not to take things at face value.

As a “technical” tech worker, I couldn’t agree more. I credit a lot of my “how to think” skills with my liberal arts education, and think it provides perhaps a not immediately obvious, yet altogether invaluable, benefit.

Read her full article

You know what’s cool? Map(). More invaluable technical insights all the time subscribe.

As the premier published resource on quirky calendars in macOS, it is my sad duty to inform the world that they have been removed. I’m not sure which update killed them, but they’re gone in Sonoma. Whenever it happened, the world got a little bit less fun.

iOS 17’s Check In safety feature seems really useful when needed. Concerned that either the time-based or location-based flavors will have too many false positives in subway rides tho.

TIL if the data that a GraphQL query is looking for has multiple types, the entire object will be removed. This is communicated via a non-halting warning, letting the “Can’t find the object” error blow up. Spent too much time debugging the error before noticing the warning 🙄

From Luke Planet’s No One Actually Wants Simplicity

I think a good test of whether you truly love simplicity is whether you are able to remove things you have added, especially code you’ve written, even when it is still providing value, because you realise it is not providing enough value.

Reminder that while USB-C is a welcome universal plug, the rest of the situation is, and will remain, a mess.

Unity exec tells Ars he’s on a mission to earn back developer trust | Ars Technica

“There was a lot more [feedback than we expected] for sure… I think that feedback has made us better, even though it has sometimes been difficult.”

Execs always trot out the “we didn’t realize” line. Frankly, that says they are either disingenuous or impossibly stupid. Either way, not trustworthy.

Reading State of CSS. Some takeaways.

  1. Respondants largely white, male, in US
  2. Highest incomes in US
  3. Most under age 45
  4. Largest usage increase: :has()
  5. Least used feature: font-palette
  6. Majority use Subgrid
  7. content-visibility use decreased
  8. Cascade Layers has low awareness
  9. Framework use trending down

I’ve been trying to collect my thoughts several days: I’m so very sad to hear of Bram Moolenaar’s passing. The author and largest maintainer of Vim for something like 30 years, his charitable work and dedication to his software was incredible. We lost a titan.

A fond farewell to DrupalCon 2023

Wrapping up at #DrupalCon and I’ve had a blast. Great to meet new friends and reconnect with old ones. Also—Pittsburgh is a great town. See everyone online!

Limit feeds to 50 items

I limited all my blog’s RSS/JSON feeds to 50 items, after realizing Hugo defaults to no limit. Hopefully that will be kinder to parsers.

TIL dynamic imports are widely supported

TIL that dynamic JavaScript imports are widely supported!

TIL the From HTTP request header. Now used for crawlers, it was originally intended for allow human users to supply their email address to the server. Innocent times.

Checked the micro.blog logs, and the cert “expired” at 10:06 a.m. (EST), so the site was down for almost 2 hours. Previously.

Site down from a cert error

Site was down for a few minutes (that I know of) due to an expired cert error. I checked the server and my cert was not expired. I rebooted nginx and it’s working again. 🤷

Exporting Mastodon Posts to My Blog

Twitter’s public implosion has redoubled my interest in blogging, and I’ve been posting more.

Through Micro.blog, I syndicate my posts to the fediverse, namely Mastodon at @chrisd@micro.blog. I have a separate Mastodon account I created years ago at @bronzehedwick@mastodon.social. I’m not yet sure how I ultimately want to structure these identities, but at the moment I have micro.blog content appear on the mastodon.social as well.

While Mastodon is great, it is not easy to migrate your content between instances, something which blogging excels at. So I wanted to import my mastodon.social archive into my blog, at least for better data ownership, but also in case I decide to make micro.blog my only active identity.

To that end, I downloaded my mastodon.social archive, and wrote a little Node script to output non-reply posts (I don’t currently have a self-hosted reply mechanism) as appropriately formatted markdown files for my Hugo site.

#!/usr/bin/env node

import { readFile, writeFile } from 'node:fs/promises';
import { Buffer } from 'node:buffer';
import { striptags } from 'striptags';

try {
    const filePath = new URL(
        '/Users/chris/Downloads/mastodon-archive/outbox.json',
        import.meta.url
    );
    const contents = await readFile(filePath, { encoding: 'utf8' });
    const data = JSON.parse(contents);
    data.orderedItems.forEach(item => {
        if (item.object.inReplyTo || !item.object.content) return;
        const unixTimestamp = Math.floor(
            new Date(item.published).getTime()/1000
        );
        const template = `+++
title = "Note on ${item.published}"
slug = "${unixTimestamp}"
date = ${item.published}
layout = 'post'
+++

${striptags(unescape(item.object.content), {allowedTags: new Set([
    'a',
    'strong',
    'em',
])})}`;

        const fileData = new Uint8Array(Buffer.from(template));
        const controller = new AbortController();
        const { signal } = controller;
        writeFile(
            `/Users/chris/Sites/Personal/chrisdeluca/content/note/${unixTimestamp}.md`,
            fileData, signal
        );
    });
} catch (err) {
    console.error(err.message);
}

That worked great, and I published my full mastodon.social archive yesterday!

Turns out, that even though all these items are well in the past, they were still ingested as new items, and five years of posts got spammed across the fediverse at once. Oops!

I don’t know how to avoid that in this situation, but apologies to everyone who had to withstand that fire hose. I don’t plan on doing it again, since I already have my archive, but any recommendations on how to avoid this for others would be really helpful.

Thanks for reading!

Use Neovim as your man pager

You may know that you can open man pages in a Neovim buffer with :Man. However, you can also configure your shell to open manual pages in a Neovim buffer when called from the command line.

First, if you’re unfamiliar, Neovim ships with the great :Man command, which opens man pages in a nicely formatted buffer. These buffers are normal Vim buffers, so come equipped with syntax highlighting, can be easily searched, and links to other manual pages can be followed with C-].

" Open the git manual page.
:Man git

You can also open man pages invoked inside Neovim’s terminal emulator using this same man buffer with a little configuration.

# This opens a man buffer?
man git

The man command can be configured to render pages with any program, controlled by the $MANPAGER environment variable.

We could set $MANPAGER to nvim, but that would cause nesting Neovim instances if called from inside a Neovim :terminal.

To work around this, we’ll need help from the neovim-remote project (at least until Neovim core adds --remote back). With that installed, we can call nvr inside a Neovim terminal buffer to open the given file in the same Neovim instance.

I personally would rather not launch a whole Neovim instance just to render a man page if I’m not already inside Neovim, so for this tip we’ll add some detection code to only set the $MANPAGER value inside Neovim. We can do this by checking the value of the $NVIM_LISTEN_ADDRESS environment variable, which will only be set inside an instance of Neovim.

We’ll use the -o flag to open the man page in a new split, to help retain the context of what you’re working on.

In your bash/zsh config file:

if [ -n "${NVIM_LISTEN_ADDRESS+x}" ]; then
  export MANPAGER="/usr/local/bin/nvr -c 'Man!' -o -"
fi

Or for the fish shell:

if test -n "$NVIM_LISTEN_ADDRESS"
  set -x MANPAGER "/usr/local/bin/nvr -c 'Man!' -o -"
end

And that’s it. Happy RTFM!

Syndicated to:

I wrote a base #css stylesheet for novels. https://www.chrisdeluca.me/article/base-css-to-style-a-novel/

Also posted to: mastodon.social/@bronzehe…