Optimizing SFSymbols with SVGO

Back in 2019, Apple introduced SFSymbols: a rich set of glyphs in a common style designed for developers to use in their apps. At the same time, they added the ability for developers to create their own custom symbols that would get all of the same useful behaviors as those provided by Apple. These custom symbols are defined in SVG files.

SVG is a rich format, and often includes more data than is necessary just to render an image. SVGO is currently one of the most widely-used tools for optimizing SVG files by stripping out unnecessary information. Its default configuration does a great job of making SVG files substantially smaller while still ensuring that they render correctly.

Unfortunately, using this default configuration on the SVG files used to define an SFSymbol removes the non-rendering information that Xcode relies on to create that symbol. By turning off a few of the default optimizations that SVGO provides, however, one can still use it successfully to optimize all of the SVG files in an Xcode project. (This includes both those you’re using for custom symbols and any used as regular images.) Here’s the necessary configuration to get it to work correctly:

export default {
    plugins: [
        name: 'preset-default',
        params: {
          overrides: {
            // disable a default plugin
            collapseGroups: false,
            cleanupIds: false

If you save that to svgo-config.mjs, you can then optimize all the SVGs in your Xcode project by running svgo --multipass --config svgo-config.mjs -rf . in your project’s root directory.

Integrating WordPress and Mastodon using ActivityPub

Last year, Automattic (which runs WordPress.com) acquired an ActivityPub plugin for the WordPress CMS/blogging platform. This caught my eye, as Elon’s sabotage of Twitter was continuing apace, finally giving me impetus to switch over to Mastodon and explore it and the other services that interoperate with it through the ActivityPub protocol.

I installed the plugin on a couple of websites I run, and have been delighted to discover several interesting things:

  • ActivityPub makes a better-than-RSS replacement for RSS. Since ActivityPub is a bidirectional protocol, using it to keep up on websites allows commenters to interact with your site without having to visit.
  • The ActivityPub plugin runs quietly alongside your other syndication methods, and doesn’t require any additional care and feeding once it’s set up.
  • The plugin can also publish content types other than weblog posts. I use an event calendar plugin on one of the sites where I use ActivityPub, and have that site configured so that each of those also is published as an ActivityPub item when I post it.
  • The plugin works great out of the box with Mastodon. I haven’t tried it with other ActivityPub clients, but it seems to have enough flexibility around how articles are published to ensure that one could get it working smoothly without much fuss, and has explicit support for many other clients.

Setting Up and Using It

I’ll use my band’s website, www.thehappyout.com, as an example. Here’s what I did:

  • Installed and configure the ActivityPub plugin on my WordPress site.
  • Using my personal Mastodon account, searched for profile @news@www.thehappyout.com and followed it. (Thanks to WebFinger support, searching for www.thehappyout.com also works.)
  • Posts on the website now appear in my Mastodon feed.
  • I can now reply to these posts, just as I would to one that had originated in Mastodon.
  • These replies go through the normal WordPress moderation channels and appear on the website just like any comments would that originated on the site itself.

It’s great to see all of this interoperating so smoothly at this point. Big props to Matthias Pfefferle & Automattic for their investment here!

Open Issues

  • It’s common to link to social media sites with a bunch of icons. I can do that to a Mastodon profile, but haven’t figured out a good way to do so with this approach.
  • When an event is published through this mechanism, the time/date and location are not included in the ActivityPub item. If there’s a way to include this sort of metadata in one’s published feed, I haven’t yet figured it out.
  • How do authors who rely on advertising on-site manage monetization if readers don’t have to visit the site? (This was a question for RSS as well, and I suspect the answers will be similar: include ads in the feed itself, or only include excerpts in the feed so readers are still encouraged to visit the site proper.)

On Games as the Art of Experiences

John Dewey suggested that many of the arts are crystallizations of ordinary human experience. Fiction is the crystallization of telling people about what happened; visual arts are the crystallization of looking around and seeing; music is the crystallization of listening. Games, I claim, are the crystallization of practicality…Fixing a broken car engine, figuring out a math proof, managing a corporation, even getting into a bar fight—each can have its own particular interest and beauty. These include the satisfaction of finding an elegant solution to an administrative problem, of dodging perfectly around an unexpected obstacle. These experiences are wonderful—but in the wild, they are far too rare. Games can concentrate those experiences. When we design games, we can sculpt the shape of the activity to make beautiful action more likely. And games can intensify and refine those aesthetic qualities, just as a painting can intensify and refine the aesthetic qualities we find in the natural sights and sounds of the world.

-Thi Nguyen (Games: Agency as Art)

2023 Holiday Update

Dear Friends,

As the dust settles from this year’s madcap Christmas celebrations, it’s time for us to look back on 2023 and share its high points with all of you with whom we don’t get to spend as much time as we’d like!

Kris invested much time and creative energy at St. Luke’s Episcopal Church, where she continues to serve as the Director of Children and Family Ministries. She has organized and coordinated all manner of classes and events, and goes to great lengths to shepherd new families into the community there. Of particular note was the Christmas Pageant, which is based on the French carol “The Friendly Beasts” and which features a wide swath of fauna that visit the holy child in the manger. In addition, by dint of hard work, exercise, and the help of a good PT team, Kris’ ribs have now largely healed from fractures sustained on a trip to a nearby waterpark. We’re very glad to have her once again firing on all cylinders!

Sean continues working on software to help doctors and manages a few folks at Doximity. He’s been playing with The Happy Out, an Irish pub band, for a year and a half now, and has delighted in seeing the band’s regular shows at The Cottage (our new favorite restaurant bar) become a meeting place for family and friends. He’s enjoyed a ton of reading this year (though the “to-read” list somehow always grows faster than the “finished” list), and is also getting close to finishing up a board game he’s been designing (with some excellent input from his monthly gaming group). Current topics of study include AI, game design, urban infrastructure and transit, audio engineering, the feasibility of space colonies, and beekeeping. (Nerd!)

We’ve been grateful for the opportunity to do some traveling this year: a marriage retreat to Galveston, a trip to Indianapolis to visit Kris’ family, a Texas coast romp with Sean’s kids, and a little overnight getaway to Fredericksburg. Kris has also gotten to know more of the Texas Hill country, embarking on several delightful day trips with girlfriends, and we’ve enjoyed several wonderful visits from various friends and family. (Come visit! We love guests and playing tour guide.)

Our progeny are doing well: Emily & Xander are still in San Marcos, fully occupied raising Juniper, our adorable granddaughter. Abi finished up her schooling and launched into her Surgical Technician career in downtown San Antonio, where she’s doing a bang-up job. Savannah is out in San Diego, enjoying her work managing a coffee shop and often providing us excellent reading suggestions. Liam works at a software agency in Dallas, where he’s advanced into increasingly responsible technical leadership roles. Maggie continues to work with her beloved animals at the SA Zoo and bought her first house, leaving us with an empty nest. (That took some getting used to!) We are grateful to see them all continuing to become kind, responsible, frequently hilarious adults, and we treasure the time we get with them.

We continue to revel in our Beacon Hill neighborhood, its mix of Spanish and English speakers, the coffee shops, taquerias, restaurants, and antique stores within an easy stroll, the monthly neighborhood happy hours, the community garden, and all of the creative, artistic, and musical friends we’ve found here. What a joy it is to be in such a lively place and close to our San Antonio family! Kris has found homes for several of the feral cats that we had adopted, leaving us with only three in the backyard currently. (They are, however, often joined by raccoons, possums, and skunks — our unofficial neighborhood mascot.)

We are grateful for your friendship — that precious currency in which we count ourselves remarkably rich. As we look forward to 2024, we wish you every blessing, and hope we’ll have an opportunity to spend time with you.

Peace and all good things,

Kris and Sean

Beagle at the Bar

Some years ago, I wrote a little jig. During a rehearsal last night, we decided to incorporate it into The Happy Out’s version of “All for me Grog”. As I needed to later communicate it to our fiddle player, I finally got around to writing it out and giving it a title inspired by an experience my wife and I had wandering through the streets of Cong on our honeymoon: “Beagle at the Bar”.

"Beagle at the Bar" melody and chords

PDF Download

The Nuclear Bodhran

While playing with The Happy Out at the San Antonio Highland Games recently, we were a bit vexed to be utterly drowned out during one of our lilting acapella tunes by the band at the next stage. The musical interlopers in question turned out to be Celtica, a group known not only for their Scandinavian-metal tinged Celtic rock, but also for their fire-belching bagpipes. While we have no aspirations to match them in volume, we were impressed with their visual flair, and decided to see what we could do to step up our own, ideally in ways that would not cause the fire marshal to raise a concerned eyebrow.

On my return home, I immediately launched into a couple hours of feverish research, followed by placing an order from Adafruit, one of my favorite electronics supply houses. A few days later, the shipment arrived, followed closely by some tinkering, prototyping, tea-drinking, assembly, thinking, coding, cursing, disassembly, soldering, and reassembly. Eventually, the smoke billowing from the chimney of my workshop abated and I emerged with v1.0 of The Nuclear Bodhran[^1]!

I was fortunate in this effort that Adafruit had published an article on their site on making the drums in a trap set sound-reactive. I used their parts list, circuit diagram, and code as a starting point for my efforts. However, I made several tweaks to their design that better suited it to my needs:

  • I used a Neopixel strip that emits light to the side, rather than outwards, which allows the LEDs to light the drumhead nicely without obstructing the sound or getting in my way while playing.
  • I added the ability to switch through several different display modes:
    1. All of the LEDs reactively light up green (standard Irish pub gig mode)
    2. All of the LEDs reactively light up in a rainbow pattern (pride parade gig mode)
    3. Irish Flag mode, where the drum is split into three regions that are illuminated in orange, green, and white
  • I used a capacitative switch library to allow me to touch the microcontroller on one of the electrical contacts to change through the modes.
  • I added code to use the built-in LED on the Gemma M0 to display a color to indicate the current mode.
  • I omitted the power switch, as the Gemma M0 has one onboard.

Project Reflections

  • I was really pleased with how quickly the lights are able to respond to the sound, tracking very accurately even the super-quick beats one gets when using both ends of the tipper to strike the drum head.
  • The brightness is good — not enough to show well outside, but certainly sufficient for an indoor setting without huge stage lighting, and perfect for the dim corners to which we are most often relegated.
  • This was my first battery-powered electronics project, and I was pleasantly surprised at how easy the Gemma controller makes it to do: the USB connection powers it when plugged into a computer for programming, and when I plug a LiPo battery into the appropriate terminal, it boots up and starts running the last code I’d loaded into it in less than a second.

I’m quite happy with how this first version turned out. For future versions, I might explore whether there are brighter light strips available, or whether using strips with more LEDs per meter would allow the lighting effects to be seen in a broader range of environments. I’ve also considered changing out the Gemma M0 for a microcontroller that supports wifi and bluetooth so that we could sync up lighting effects on multiple instruments or even have the audience send texts from their phones to change the lighting effects. (There is no end to my nerdiness.)

I’ll be trotting this out for the first time at The Cottage this weekend; looking forward to seeing how it’s received!

Resources to Build Your Own

[^1]: Not actually nuclear. But actually a bodhran.

Reflection on Making Video Games and Child Rearing

I finished reading “Blood, Sweat, and Pixels” this morning. Great read, and an excellent window into the video game industry and the toll it exacts from those working in it.

When I got laid off from EA back in 2004 (they were moving the Origin team from Austin to California), I took a job at Texas State University next. There were a few reasons for choosing that role, but one was that I wanted to be more present for the raising of my young kids than my previous commute and the studio’s occasional crunch time allowed. Seeing how endemic the practices of crunch and overtime are in the industry, I’m even more glad now that I made that decision. (Plus, a few of my most treasured friendships grew from that time at the University.)

In a bit of interesting synchronicity, as I’m reflecting on this, my youngest is moving out to her own place, leaving me with an empty nest for the first time in 27 years. My kids have all turned out to be wonderful adults, and I’m so grateful to have been able to make the most of those fleeting years when they were growing up under the same roof with me.

I still occasionally dream about being a part of building another terrific game; but given how much that industry asks of its people, I’m unwilling to pay that relational price. I’m so glad to have had the opportunity with Ultima Online, but that window seems to have closed, and I’m fine with that. Most days.

Creme Brûlée Day 2022

Several years ago, I designated the day before Thanksgiving as Creme Brûlée Day. My extended family now observes it, naturally enough, by getting together and making the titular dessert while visiting, playing games, doing other Thanksgiving prep, and enjoying being together.

Part of the tradition is to devise new Brûlée recipes and try them out. In the past, we’ve come up with recipes for Mexican Chocolate (a keeper!), Sriracha (decidedly not a keeper), and Parmesan cheese (far better than it sounds).

This year, our experiments were all based on the same custard base:

  • 1/4 cup sugar
  • 3 large egg yolks
  • 1/2 quart heavy cream

We tried even more variations this year than usual. After much deliberation, we settled on trying the following:

  • The aforementioned Mexican Chocolate. Still delightful.
  • Add 3tbsp of PB2 powdered peanut butter. We’d tried a peanut butter Brûlée a few years back and were pretty disappointed by it. This was hugely better — probably my favorite variation of the day. A bit like a Reese’s cup, but creamier.
  • Add 2tbsp of Anthony’s Cheddar Cheese powder. Like our parmesan experiment last year, the combination of sweet and salty was better than it sounds at first blush. Not bad, but not spectacular.
  • Add 1/3tsp of maple extract. A little of the flavoring went a long way, but it was extremely nice! As you might expect, very similar to maple creme candies.
  • Add 3tbsp of Kahlua. This was excellent; another favorite of the day. The sugar glass works really well with the flavors of the liqueur. Abby’s favorite, and Kris said it was restaurant-worthy.

We ate about half of the quadruple batch we made (having learned from years past), but still have plenty to take to our Thanksgiving feast tomorrow. A delightful time for both palate and soul!

Poppy’s Traveling Song

Hey musical nerd-friends! If anybody’s been curious about Poppy’s traveling song from Episode 5 of Rings of Power, I took the time to chart it out this morning, as I wanted to perform it with The Happy Out. Help yourself! Fair use disclaimers apply: not for reproduction, for personal study only, etc.

{title: This Wandering Day}
{key: Bb}
{time: 3/4}

(drone on chord)
[Bb]The sun is fast falling beneath trees of stone
The light in the tower, no longer my home
Past eyes of pale fire, black sand for my bed
I'd trade all I've known for the unknown ahead

[Bb]Call to me, call to me
[Eb]Lands far [Bb]away
For [Bb]I must now wander this [F]wandering day
A[Gm]way I must [Eb]wander this [F]wandering [Bb]day

Of [Bb]drink I have little, and [Eb]food I have [Bb]less
My [F]strength tells me [Gm]no, but the [Eb]path demands yes
My [F]legs are so [Eb]short and the [Bb]way is so [F]long
I've [Gm]no rest nor [Eb]comfort, no [F]comfort but [Bb]song

[Bb]Sing to me, sing to me
[Eb]Lands far [Bb]away
Oh [Bb]rise up and guide me this [F]wandering day
Please [Gm]promise to [Eb]find me this [F]wandering [Bb]day

At [Bb]last comes their answer through [Eb]cold and through [Bb]frost
That [F]not all who [Gm]wonder or [Eb]wander are lost
No [F]matter the [Eb]sorrow, no [Bb]matter the [F]cost
That [Gm]not all who [Eb]wonder or [F]wander are [Bb]lost