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.)

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.

A Bit of DALL-E

I’ve recently gotten access to DALL-E, an artificial intelligence program to which you can provide prompts and it outputs images based on those prompts. It’s an incredible piece of tech, and often hilarious. I just gave it the prompt “Jesus as a superhero” and got this back:

BTW: I know Jesus wasn’t a white dude. This demonstrates one of the perils of inaccurate training sets for machine learning models.

“Astronauts kung fu fighting” is also pretty fun:

Making of a LEGO Saturn V Display

After many months of off-and-on work, I’ve finally finished creating an appropriate setting for the LEGO Saturn V that my fine son Liam gave me.

This was a fun project: electronics, 3D printing, CNC milling, programming, and audio editing all combined to get the effects I was looking for. If you’re interested in the details, please check out my writeup on its construction.

Setting Up Live Streaming For Facebook

My lovely bride and I shared a few songs on Facebook Live last night to ring out 2020. The setup ended up being complex enough that I thought I’d document it here for anyone (including my future self) who might find it useful. Here’s a quick diagram of the flow:

And a few details:

  • The mic was a large diaphragm condenser (AT2020) that our friend Brian graciously lent us. It worked really well for picking up the sound from our singing and instruments in a fairly large space. I also fed my guitar in directly, which allowed me to get a little more low-end from that instrument and to process its signal independently of everything else going on in the room.
  • The audio interface was a little 2 channel Behringer (UMC202HD), which was solid and sounded great. More channels would have been useful, however, to be able to feed Kris’ guitar into the system directly as well and conceivably add a mic.
  • MainStage is fantastically fun and flexible, though it has a little bit of a learning curve. I used it to compress, EQ, and mix the incoming signals, as well as to provide the reverb for the pennywhistle piece. (Thanks to my son Liam for buying a copy!)
  • I used the MIDI controller (an AKAI MPKmini) only to turn on and off the reverb, though it can also easily drive virtual instruments, trigger loops, adjust patch parameters, etc. in MainStage.
  • Blackhole is a nice little audio driver that allows you to pass audio from one program to another on a Mac. In this case, I just used it to allow MainStage to send a signal to OBS.
  • For the video, I determined that the camera on an iPhone does a much nicer job capturing clean video than the Facetime camera that’s built into the Mac, so I used a program called EpocCam that allows one to use the phone camera as a webcam.
  • OBS is a software package that’s widely used for real time streaming. I’d originally not planned to use it, but when we did some tests beforehand, the video quality using Facebook’s built-in tools with the camera signal was terrible — super-compressed with a lot of nasty artifacts. OBS allowed me to pre-compress the video signal before sending it up to Facebook, which resulted in a much nicer image and far more modest bandwidth requirements.
  • Seriously, don’t use Facebook’s “camera” option for live streaming.
  • Finally, we used Facebook Live with a streaming key to share the video into a Facebook Live event. This was great from a standpoint of getting the word out to our friends, but the video was still fairly stuttery and unreliable at points. (The audio seemed rock-solid though, which was great. If you need to compromise on something when streaming, choppy audio is much worse than sub-par video.) OBS seemed to be cranking the stream out at a reliable framerate, so I’m pretty sure the video issues were on Facebook’s side.

On the whole, we were very happy with how this setup worked out. Having so many moving parts felt like a precarious house of cards, but all of the components worked reliably. And with the flexibility that OBS and MainStage bring, it would be straightforward to add multiple camera angles, do more sophisticated audio processing, or switch to a different streaming service to raise our production standards in the future. One potential limitation would be the processing power of the Mac running the show, but as is, this setup didn’t ask more than about 20% CPU of the 2019 16″ MacBook Pro that we were using. (And the new Apple Silicon will provide substantially more headroom for this sort of processing.)

Lastly, here are a few photos of the production rig. As with so many things, it’s a lot messier in real life than in a flowchart!

13 Tips for Working Remotely

I’ve worked in a lot of different environments over the years. Working with a distributed team is one of my favorite ways to get things done, but it comes with its own sets of challenges that aren’t obvious at first blush. Here are 13 things I wish I’d known when I started working with colleagues who are geographically dispersed:

  1. Overcommunicate: Communication happens pretty naturally when you’re sitting next to someone, but when you’re remote, it takes more of an effort. Make that effort! Respond quickly to email and Slack, even if it’s just to say “Got it!” or “Working on it; I’ll have it done Tuesday!” When you get a request from a remote teammate, you need to explicitly tell them that you are working on it and when you expect it to be done. They have no other way of knowing.
  2. Give your Team the Benefit of the Doubt: We all make mistakes sometimes! Don’t take it personally if team members forget to include you once in a while. Do, however, graciously let them know how you feel and certainly when it impacts your ability to work effectively. It’s easier to tackle issues earlier when they’re small.
  3. Presentation: Think about what creates a professional impression, and make it happen, both with teammates and with customers. At a minimum, this will include having a good quality microphone/headphones and webcam for video conferences, using a solid high-speed internet connection, and looking as professional as you would in the office. (These are in addition to practices that are universal, regardless of whether you’re in the office or not: turn up to meetings on time, speak and listen carefully, etc.) You might also think about what’s behind you on your video calls, having good lighting so that folks can see your face well, having a low-noise environment so that others can hear you well, etc. Use video as much as possible; being able to see others’ faces gives us lots of insight into their thoughts and feelings that are otherwise easily missed.
  4. Arrange Pairing Sessions: It’s especially important when working remote to deliberately keep relationships vital with coworkers, which is helpful for building trust and working smoothly together. One effective way to do this is by working together on a task for a period of time. “Hey, I’ve got this design due Thursday and I’d love to have another set of eyes on it. Could we work together on it for an hour or two Monday?” This also helps spread knowledge about projects around your team and company.
  5. Initiate Social Time: Getting face-to-face time with your colleagues is important, and is tougher to do at a distance. Join others for a weekly Zoom happy hour, a lunchtime Jackbox game, or just a check-in. Start one of these if they don’t already exist.
  6. Use High-Bandwidth Communications, But Record Decisions: Reaching consensus can be hard, and the delays that email introduces make it even tougher. Whenever possible, have conversations with video in real-time. When you’ve reached consensus, then write a quick summary of that chat and share it in Slack or other appropriate channels. This ensures that you and the other people in the conversation have a common understanding of the conclusion you reached and that others are aware of, understand, and get the benefit of your discussion.
  7. Let Your Team Know Your Status: Whenever you sign on or off, even if it’s just to go run an errand, let your team know and when you’ll be back. This helps others plan their time around your availability.
  8. Focus Time: One of the benefits of setting up your own work environment is that you can limit distractions. If you need to go head-down on something for a few hours, do it! Let your team know that you’re going to be concentrating for a period of time and set Slack to Do Not Disturb. (Assure the team that they’re welcome to break in if there’s an emergency.)
  9. Set Aside Physical Work Space: Having dedicated space for work not only makes it easier to create a good environment but also helps get into the work mindset. Important things to pay attention to when you’re setting up your space: safety, comfort, necessary tools, and a minimum of distractions.
  10. Keep it Classy: Humans are not perfect communicators. Text-based communication misses 80% of face to face communication that is non-verbal. Thus, we need to be especially careful to communicate in a way that’s respectful and kind when we’re remote. Verify your assumptions and sense-making. Saying “please” and “thank you” goes a long way.
  11. Stick to a Schedule: Having a regular schedule not only helps your team, as they’ll know when you’ll be reachable, but also helps you. Regular hours tend to result in better sleep, more focused work, and the ability to feel good about putting work aside at the end of your scheduled time. (Though of course, when you need to make an exception to your regular schedule, don’t hesitate — just let your team know!)
  12. Take Breaks: A team in an office takes breaks during the day; we need those breaks at home too. Have a walk, play with your dog, get a snack! (Just let your team know if you’ll be unavailable for more than 10-15 minutes.) Also, don’t mistake having your office at home for an expectation that you’ll be working all the time; take your weekends and evenings off.
  13. Set Up Your Work Hours in Calendar: Most calendar systems have a handy feature that will let meeting organizers know when they’re trying to schedule a meeting outside your work hours. Set it up! This will let others know in a low-friction way when they can expect you to be available (and when they shouldn’t).

On COVID Contact Tracing Apps

I’ve heard some friends express concerns about these being used for government surveillance. As a civil libertarian, I share your reservations.

I’ve also been a mobile developer for nearly a decade and have done a good deal of professional work around the location-tracking and proximity detection technologies that these rely on, so know firsthand what these apps can do.

My short take: if an app asks for access to your location data or contact list, granting that will give more info than you want to share. If it instead asks to use the privacy-preserving contact-tracing capabilities Apple and Google built into the latest versions of their operating systems, it cannot be used to track your location or any personally-identifiable information, and you can use it with confidence.

None of these have been released in the US yet, but they should be coming soon. I’ll share further info on them when they are.

1945 is Now on Tabletop Simulator

Some of you may remember that, a few years back, my son Liam and I designed, and my eldest daughter Emily illustrated, a card game. The elevator pitch was “like Risk but with cards,” and we christened it “1945.” It has remained a family favorite since we created it.

It’s been out of print in its physical form for a while now due to some shenanigans with my printer, but I’ve just finished porting it to be playable in Tabletop Simulator. If you’ve got TS (which is near-essential for board game fans during this time of social isolation) you can now play 1945 for free!

Happy quarantine!

1945 on Steam Workshop

Heading to HEB

I’m happy to share the news that I’ll soon be starting a new role at HEB, the much-loved Texas grocery chain, as a Sr. Developer on their Curbside team. While I’ve really enjoyed and appreciated my time with some outstanding and amazing human beings at Handsome, I’m excited about this new professional chapter for a couple of reasons:

First off, I find the craft of software development — building intricate, beautiful mechanisms out of logic and aether — to be deeply engaging and interesting. I will be able to focus on that aspect of my work more squarely here than has been the case since I started taking on management roles several years back.

I am also a great fan of having the centers of one’s professional and personal lives close to one another. Being able to invite colleagues over for dinner, avoiding endless hours on the interstate, and burning less fossil fuel merely to be places are all important to me. Since we moved to San Antonio this year, working 10 minutes away feels like a big quality of life improvement.

In addition to being close, I’m excited about the specific location where I’ll be working: the headquarters campus is a lovely site of an old arsenal that was founded in 1859 to supply the forts on the Texas frontier. It’s along the San Antonio River, downstream a bit from the main segment of the Riverwalk, along a boating-friendly stretch that will allow me to toss a kayak in the water and go paddling after work. And HEB has plans for a beautiful, expansive tech center on campus to open in a couple of years.

Finally, the company has a tremendous reputation for being a great place to work. I’ve long appreciated their commitment to serving the communities in which they operate, donating more than 5% of their gross earnings, helping food banks, etc. I’m glad to see that they have a similarly good reputation as an employer, and are investing deeply in building their technology capabilities and team.

I’ll be starting on February 10; I’m eager to invest my professional energies in service of a company for which I have respect and high expectations for its future, in the city that I grew up in, love, and still feels like home.