Lane Sawyer🌹

Just trying to leave the world a little better than I found it.

2021 Year In Review

As the first year of the decade comes to a close, I can breath a sigh of relief. While 2021 wasn't great, at least this wasn't 2020.

Personally, I had a pretty solid year. As a country and global society, things could've gone much better.

Let's get the global bad out of the way first:

  • The January 6th Insurrection, which will be discussed as one of the lower points in US history for decades
  • Carbon emissions went back up after a slight lull from the pandemic
  • The pandemic remained a pandemic, even after an absurdly effective vaccine was quickly created
  • Seattle had an election that somehow resulted in us electing a Republican who joined the GOP after Trump took it over
  • Dramatic, unseasonable, and deadly weather events happened in every place I've ever lived, including the hottest day ever recorded in Seattle and the coldest day in the last 30 years
  • Breath of the Wild 2 was not released
  • Many other things that kept me awake at night that I've apparently successfully forgotten

But after a year like 2020, I've learned to manage my existential horror so while the world may be literally burning all around me, at least I can enjoy my life and hang on to the sliver of hope that we can turn this train around before we go completely off the rails.

And with that nasty list out of the way, it's time to be positive and do some navel gazing.

Every year since 2015 I've put together a "52 Things" list. I stopped publishing them publicly after a couple years, but I've continued the practice of setting 52 goals across some fairly consistent categories:

  • Personal
  • Health
  • Finances
  • Social
  • Experiences
  • Media
  • Work

In 2021 I finished all of my social goals, all but one of my media and financial goals, and a spattering of others for the remaining categories. All together, I finished 24 of the 52! That's not too bad, and is line with most other years (with the exception of 2020 because COVID blew up my ability to do a lot of things I had planned).

Some highlights from my goals this year are:

  • Finishing 77 books
  • Climbing two V4s at the bouldering gym
  • Making a new friend, even during a pandemic
  • Hitting all of my financial savings goals
  • Getting vaccinated

Outside of goals my year also went really well.

Work was a big part of why 2021 was a good year for me. I really enjoyed settling into my role as a software engineer building websites to display scientific data. I've never been this happy with work before, and I wish I would've gotten out of consulting way before 2020. I'm now getting paid my highest salary ever! It's weird that I got a pay increase for working in the non-profit industry... It's almost like my skill set wasn't valued and I wasn't compensated fairly as a consultant (but that's a post for another day). Working in the non-profit industry has been rewarding, and I have a great team of people I work with every day to build quality, useful software. Plus we have a great work/life balance culture of working hard but calling it quits at the end of the day. While I still don't get to program professionally with the Rust programming language, I do enjoy what I do and that makes life much better.

Outside of work I tried to keep myself as busy as a pandemic would allow. I'm the Dungeon Master for a D&D group with five of my friends, and we had a good six or seven sessions throughout the year. Building a world and seeing others explore it is satisfying, and I like to think that I'm getting better at running games so they stay fun for everyone.

In addition to sitting around a table telling stories, I climbed regularly with a group of friends and while my waistline is not in great shape, I'm climbing at the highest level of my entire life! My goal is to move up another difficulty level in 2022, which will require slimming down a bit so I'm excited for that.

I also reconnected with my ex-wife after three years of space and we got back together, to the immense delight of our dog Kaladin. While there's been some bumps in the road as we get to know each other again, it's going really well so far and being with them makes me happy!

Finally, I got to spend a lot of time with family. Between a two week vacation in the summer and a month at my parents house this winter, I've gotten a lot of face time with immediate and extended family. Living in Seattle means I don't see them as often, since most of my family is in Utah. I'm grateful my profession allows me the flexibility to work from just about anywhere, and long trips to see family will likely be something I do every year from now on!

So yeah, 2021 wasn't too bad. I've got a new batch of goals that I'm excited to work on, and I'm optimistic that I can get more than half finished this year!

Hope you all are as excited for the coming year as I am.

We've got this.

Government as a Service (GaaS): How the Federal Government Could Streamline State Management

Last week, the Missouri governor showed the world his technological illiteracy by vowing to prosecute a "hacker" that brought a major data leak to the government's attention. The entire tech community had a big laugh, since the government itself was sending Social Security Numbers to users that could be easily found with the barest modicum of tech know-how.

The governor's public blunder never should have happened. The fact that he publicly stated his ignorance in such an embarrassing manner demonstrates that nobody in his advisory circle knew enough about technology to tell him to stop. Nobody he knew understood that it was the government's mistake, even though the data breach was responsibly reported.

It's not a big leap to assume that nobody competent is leading Missouri's technology departments. I shudder to think what else in the state is wide-open for attackers.

Sure, it's easy to call out government incompetency (especially when it comes to technology). It's practically an American past time. But things like this keep happening and we should keep getting upset until the issue is solved.

Securing IT systems is no trivial task, and we make it incredibly difficult on ourselves due to the very structure of the US federal government system. States have an incredible amount of power, which means the United States has about 50 different ways of doing any one thing when it comes to running the state IT systems. That's a huge attack surface for malicious actors to find their way into.

But regardless of which state we're talking about they all need to do similar things that involve information technology. Here are just a few things I could think of off the top of my head:

  • Legislation
  • City planning
  • Taxes
  • Voting
  • DMV
  • Communications
  • Infrastructure maintenance
  • Citizen feedback
  • COVID reporting and notifying

I could keep going.

So why are we creating 50 different IT systems for these? As a small example, I live in Washington, which has a great legislation system that even allows citizens to provide feedback on bills. Looking at the same type of site from Texas, the last state I lived in, their legislation system leaves much to be desired, especially because there's no way to provide feedback on the very bills you're searching.

I'm sure both state's IT departments (or potentially hired contractors) put a lot of hours into these systems. It's great they're available, but sad that my friends in Texas don't have the same tools of democracy I have. And looking back at the utter incompetency of Missouri, many of these systems across the US were likely built on a shoestring budget by people who don't have an understanding of IT security.

All this leads me to ask: why aren't states working together to provide a great, secure technology experience for their citizens?

I argue that our federalist system discourages coordination, at least when it comes to IT systems.

One benefit to the federal system is that states get to be "laboratories of democracy". Each state can adapt their laws to its specific citizens, with a federal government theoretically providing a common floor of basic human rights that every state has to provide. Sometimes those "experiments" do leak over to other states, until things that used to be unthinkable (gay marriage or cannabis legalization) are essentially the law of the land, even without federal support. That can be a pretty great way to run a country, but it does have its pitfalls. One of which is the fragmentation of technology solutions, further exacerbating our already inefficient bureaucracy.

Maybe I'm just ignorant, but I haven't seen collaborative thinking when it comes to building and running the information technology powering our state, county, and local governments. Part of it is likely because the Internet and supporting technologies are relatively new and the machinery of government moves deliberately slow. Another part is that private industry sucks up the best IT talent just to put them to work on milking a few more dollars out of ad clicks instead of positively contributing to society. And yet another is because the one government body in place to facilitate coordination between states simply hasn't done it yet!

Now is the perfect time for the US Digital Service to create a Government as a Service (GaaS) platform.

The federal government should lead the charge in researching and developing a suite of open source state management tools that are free to use and expand upon. This would create a cooperative IT community where states can add to these systems based on their unique circumstances and make those improvements available to others. It also greatly reduces the attack vector of potential hackers, since these handful of common systems can be more efficiently hardened than all of the unique systems built in each state. Hell, even private businesses would be free to use or contribute to any of the tools that overlap with their needs.

This doesn't even have to be done with changing laws, as far as I'm aware (though I'm no lawyer). The US Digital Service could be instructed to coordinate or build these tools through an executive order. New laws enabling this kind of digital transformation would further accelerate the quality of these shared tools, especially when it comes to allocating funds towards making the systems private and secure. And with the USDS leading the way, these systems would be fantastic. The USDS is already working on a common set of tools to standardize federal websites to create a unified user experience. They would be in the perfect position to help states take advantage of the tools already built and create even more quality tech to support state governance.

Obviously, some people will have concerns with such coordination. I imagine some folks are happy that there's no federal coordination of IT strategy in order to protect against some sort of centralized government technology takeover. But to mitigate those fears, these tools would be open source and voluntary to use. In addition, information privacy should be a major concern when creating all of these new systems. The latest encryption methods should be employed with no backdoors, and independent audits should be performed to keep everyone using these systems safe from bad actors, both internal and external.

Imagine the time and money saved if all US states coordinated in building an open source suite of government management tools.

Your next trip to the DMV could take minutes, no matter what state you live in. You could easily find and look through an interactive breakdown of your city's finances. You no longer would have to pay some company to file your state and federal taxes. You city's administration budget could be slashed, all while getting a more-responsive government.

And best of all, you could finally sleep soundly at night knowing your fellow citizens in other states are getting just as excellent an experience interacting with their government online as you are.

Podcasting's Walled Garden Problem

If you know me well, you know I'm a tad bit into podcasts. I listen to 28 different shows regularly, with 40 other shows I pick and choose from when I have the time. If I'm not listening to an audiobook, chances are I'm devouring a podcast.

I've been in love with Podcasts since I discovered them over a decade ago. It's basically internet radio, except you're the DJ. Distributed through the ubiquitous RSS feed technology, they're easy to find, share, and consume.

But Spotify (and some other media organizations) are intent on changing that.

When Spotify acquired Gimlet in 2019, I felt a change in the wind. Despite saying they'd keep existing podcasts available outside of Spotify, I knew it was just a matter of time before that promise was broken.

And here we are now, in 2021. Two of my favorite shows, How to Save a Planet and Science Vs have both become Spotify exclusives.

The hosts made many announcements leading up to their show's move to Spotify, making it clear that you could still listen for "free", as long as you did it on Spotify.

Now two excellent scientific journalism podcasts are locked away behind a Spotify account, unavailable to those of us who refuse to have two different apps for podcasting or don't want to move all their podcasts over to Spotify. I'm particularly disappointed in How to Save a Planet, since it was the one show that helped partially reduce my climate anxiety. They covered all the great work being done to alleviate the worst aspects of climate change, and it was a legitimate bright spot in my week to hear about new technologies that might save the world.

All of this wouldn't be a particularly annoying problem if Spotify's app actually worked well for podcasts. There's no way to add custom feeds, which is a must-have for people like me who support my favorite podcasters on Patreon and have private RSS links that provide access to bonus content. To listen on Spotify, I'd have to maintain podcast lists on two different apps for no good reason.

And once you try to listen to a podcast on Spotify, you quickly realize it's a horrific experience. Podcasting is an afterthought for the developers of Spotify. They only recently added speed controls after years of having podcasts available, and managing the podcasts you follow and which episodes you want to listen to is an unintuitive experience.

Nobody would choose Spotify as their podcast listening app of choice, so Spotify has decided to acquire great shows and force fans to use their application in an attempt to fully capture the revenue stream for those shows.

Once you throw money into the equation, this all makes perfect sense. If a podcast is only available on Spotify (even if it's free), Spotify will receive all ad revenue for the shows since it can use its existing ad placement technology that was developed on the music side of the business. They want to control all aspects of the show in order to maximize their profit. You have to have a Spotify account to listen to the podcast, which makes it that much easier to turn a listener into a paying Spotify user.

Someone at Spotify must have run the numbers and shown that putting its shows in their walled garden and losing listeners is still more profitable than having it widely available. It's a downright shame, since many of the Gimlet shows they acquired are incredibly informative and contain information that will make this world a better place.

I fully expect this trend to continue, and probably accelerate. That's why I'm a huge proponent of paying for your favorite shows through sites like Patreon. Directly supporting artists with small monthly contributions reduces their dependence on ads and helps keep them independent.

If you have a favorite show, please consider regularly supporting them using whichever method they prefer. The consolidation of podcast networks and ownership will continue to create these walled gardens, leading to wonderful content being hidden from millions of listeners.

It's up to passionate listeners to support these artists enough that they don't have to sell their souls to the giant corporations just looking to milk them for ad revenue. Please do your part and keep the information flowing freely, just as it was intended to do.

Living with Seattle's Long Dark

It's that time of year again, where the sun sets before 7 PM and a perpetually gray blanket of clouds once again descends on the Emerald City.

The Long Dark in Seattle has begun.

As an introvert, fall and winter are two of my favorite seasons here in Seattle. The city slows down, social events become less frequent but more cozy, and I get to snuggle up in a blanket and read while listening to the rain drumming on the porch.

But as someone with depression, fall and winter can be the most difficult seasons of the year. At its worst, the Long Dark gives us a paltry 8.5 hours of sunlight. Add in the November reversion to standard time and my night owl sleeping habits... I'm lucky to see 6 of those hours some days.

Thankfully after living in Seattle for five years I've figured out a variety ways to cope with it. So far, these are a handful of things that have worked well:

  • Long lunchtime walks with my dog to soak in the sun
  • Bright lights indoors until 8 or 9 PM
  • Hot coffee to warm me up and wake me up
  • Regularly hitting the climbing gym
  • Hot pho and other soups
  • Movie nights with friends
  • Snowboarding adventures
  • Weekend hikes and camping trips
  • Hobbies like video games and programming that blast my eyes with light
  • Vacations down south, often in Utah to visit family
  • Accepting that my brain will be a little down on itself for a while

It took me a while to build up a good toolkit to fight back against the literal and figurative darkness. But now that it's in place, I've been weathering the worst of the winters well.

While the Long Dark may sometimes be tough, the rest of the year more than makes up for it.

I love this city!

The Why and How of Rust Declarative Macros

In order to prepare to conduct a technical interview of a potential future co-worker, I decided to try to solve the problem we would be presenting to the candidate. I chose to do it in Rust (even though we don't use Rust on my team) so that I could approach the problem with a fresh perspective and potentially learn some new things about my favorite programming language.

It turns out revisiting an old problem using a dramatically different programming language will teach you a lot! I wrote four different solutions using different approaches and patterns, which helped me better understand Rust's standard library and how to write more "Rusty" code. In addition it prepared me to better understand what the interviewee might do in the interview so I can ask good questions to see how they think.

But the biggest thing I learned through this exercise was how to write Rust declarative macros, which this post is all about.

Why Use Declarative Macros

I've never worked with a language that uses macros before and reading about them has always scared me a little. Code that writes other code, but with special syntax? Yikes. Since meta-programming can become extremely complicated, I've never reached for it to solve any problems, but I stumbled across a good opportunity to dive into it when writing tests for my interview answers!

While testing my potential solutions, I found myself repeating the same exact lines of code over and over, with minor variations:

// Tweak the test array to check the different conditions in each test
let test_array = vec![3, 3, 4, 2, 4, 2, 4, 4];

let first_result = find_answer_1(&test_array);
let second_result = find_answer_2(&test_array);
let third_result = find_answer_3(&test_array);
let forth_result = find_answer_4(&test_array);
// Add another line here in every test when a new function is made

assert_eq!(4, *first_result.unwrap());
assert_eq!(4, *second_result.unwrap());
assert_eq!(4, *third_result.unwrap());
assert_eq!(4, *forth_result.unwrap());
// Add another line here in every test when a new function is made

In addition, whenever I added another solution to the problem I had to update multiple lines in every test case. It was becoming a real headache, and it only got worse with every new problem solution function I wrote.

Thankfully, declarative macros are the perfect tool for writing repetitive code with minor variations!

Now instead of writing all those lines for each test, I only needed to do the following to test each case:

    // The answer based on the list below
    // The test's input data
    &[3, 3, 4, 2, 4, 4, 2, 4, 4],
    // The names of the functions I want to test
    // Add another function name here whenever it's created

Isn't that dramatically better? It's extendable too, so when I get an itch to write another solution to the problem in the future, I can quickly tack it onto the end of the macro's arguments and it will also get tested.

How to Write Declarative Macros

So now that we've seen how a declarative macro can simplify writing code, let's dig into how to write them. The following code block is the final macro I came up with, along with a copious number of comments describing the syntax, since there are some different symbols used compared to writing regular Rust that you may not be familiar with:

// macro_rules! is the macro used to create declarative macros
//   test_find_answer_functions is the name of this macro
macro_rules! test_find_answer_functions {
    // Match macro usage where None is the expected output
    //   (matches the literal None, is not macro syntax)
    // - $test_array:expr - array of values to search for the answer
    //   (expr means any expression, e.g. vec![1, 2, 3])
    // - $function:ident - name of the function to test against
    //   (ident means an identifier, i.e. the function's name)
    // - $(__),+ - repeat 1 or more times
    (None, $test_array:expr, $($function:ident),+) => {
        // syntax for repeating based on the number of functions provided
            // Call function with test data, assert the result is None
            assert_eq!(None, $function($test_array));
    // Match macro usage where generic type T is the expected output
    // - $answer:expr - value of T we expect to be the answer
    // - $test_array:expr - same array as the None branch
    // - $function:ident - same list of functions as the None branch
    ($answer:expr, $test_array:expr, $($function:ident),+) => {
        // syntax for repeating based on the number of functions provided
            // Call function with test data and assert the result is the answer
            assert_eq!($answer, *$function($test_array).unwrap());

Like I said before, macros are a bit weird. It's got a whole "who programs the programs" vibe to it that requires you to think about your code's structure differently, so I definitely ran into some issues when making the macro that wrote my tests for me.

If you ever want to try writing your own Rust declarative macros, you'll find a few of the roadblocks I faced written out below so you can avoid them yourself:

Issue 1

The first issue I ran into is that I didn't have a clear idea of what an :expr or an :ident was, so I was getting some weird errors. After reading through the metavariables section of the Rust Reference (which is a deep dive into the inner workings of Rust), I found my problem. I was treating my function name as an expr instead of an ident. Turns out expr is any valid Rust expression, like the value I wanted to test and the list of values to test against, and ident is any identifier, like the names I gave my functions. Little facepalm moment there, but solved easily enough.

Issue 2

The second issue was dealing with the two different patterns of test code. Some of my tests expected a result to be found, while some expected no solution to the test data provided. This led to two different assertions:

// For data with an answer
let test_array = vec![3, 3, 4, 2, 4, 2, 4, 4];
let first_result = find_answer_1(&test_array);
assert_eq!(4, *first_result.unwrap());

// For data without an answer
let test_array = vec![3, 3, 4, 2, 4, 2];
let first_result = find_answer_1(&test_array);
assert_eq!(None, first_result);

That pesky dereference (*) and .unwrap() in the example with an answer is totally different than the second example, where we only have to check the first_result Option to see if it's None!

Thankfully, Rust declarative macros support the same powerful pattern matching that Rust uses. In the macro code above, you'll see two different cases. One for None and the other for Some result.

And that order is important! When writing patterns, you want to start with the most specific at the top so that it's matched against before its more general version. Since None is a macro metavariable of type expr, putting the second pattern first would mean None matched that more generic pattern. I spent a few minutes stuck there until I remembered that particular rule of pattern matching.

Issue 3

Finally, I fought the borrow checker for a bit, since I couldn't easily tell what the final output of my macro would be. Rather than randomly throw * or & into my macro, I decided to finally figure out how to view the compiled code with the following command:

rustc --pretty expanded -Z unstable-options src/ --test

Now that's a bit more complicated than I would prefer for a debugging command, but it makes sense once it's broken down:

  • rustc is the Rust compiler
  • In order to use the --pretty expanded flag to preserve spacing after compilation, -Z unstable-options is required
  • -Z unstable-options requires the nightly compiler (which can be turned on for a single workspace using rustup override set nightly)
  • src/ is the name of the file to compile, which is the one I'm writing my code in
  • --test means to compile the test code, which I needed since my macros are only used in the tests

Unfortunately, that final command expands all macros, including the final code for things like assert_eq! and the #[test] attributes on the tests themselves, so it took me a little bit of digging to find my specific macro code. But once I found my macro's output, I could clearly see the borrow checker problem and fix it!

Why Not Use Plain Rust?

I could've written a solution using plain ol' Rust, avoiding macros entirely. The main reason I didn't was I simply forgot that was an option and finished the macro before I remembered that you could pass functions to other functions (which I absolutely love to do!).

I decided to write up a solution using functions. In the end I still feel like macros are a better fit in terms of ergonomics. I had to write two different functions, one for the Some case (when a solution is found) and another for the None case (when there is no solution):

fn test_find_answer_functions_some<T, F>(answer: T, data: &[T], funcs: Vec<F>)
    T: Eq + Hash + Debug,
    F: FnOnce(&[T]) -> Option<&T>,
    for func in funcs {
        assert_eq!(answer, *func(data).unwrap())

fn test_find_answer_functions_none<T, F>(answer: Option<&T>, data: &[T], funcs: Vec<F>)
    T: Eq + Hash + Debug,
    F: FnOnce(&[T]) -> Option<&T>,
    for func in funcs {
        assert_eq!(answer, func(data));

I could've written a single function that handles both scenarios by passing in an option as the answer parameter for the Some case, but that led to me writing this absolutely hideous answer argument as seen below:

    &[3, 3, 4, 2, 4, 4, 2, 4, 4],

Wrapping the answer in a Some instead of a naked 4 like I could do with the macro was just too much for my perfectionist brain to handle.

In order to match the prettier user-friendly macro syntax, two functions were required. Even then, I had an ugly .to_vec() that I couldn't get rid of (although I'm sure there's a way to do so if I spent a little more time on it):

    &[3, 3, 4, 2, 4, 4, 2, 4, 4],

In addition to the less than ideal user interface, the function approach requires a bit more of a heavy lift on the runtime side of things. A macro literally prints out code, and that resulting code can be optimized by the compiler. The functional approach happens dynamically at runtime, so there's a bit of a performance cost there. This toy example isn't concerned with performance, but it is something to consider when making a decision between the two approaches.

Wrapping Up

By this point you should have a high-level understanding of what Rust declarative macros are, where they might be helpful, and some potential issues you might face when writing your own.

While my example was a little contrived, it was a real-world usage of macros that made my life as a programmer a little bit easier and got me excited to look for more substantial opportunities to use macros in the future.

Further details regarding declarative and other macros can be found in the official Rust book, which is one of the best resources out there for learning the language and should be on the reading list of anyone wanting to become proficient in Rust. If you found this article interesting, I think you'd really enjoy the book. It's one of the best examples of approachable technical writing I've ever come across.

If you have questions or comments, feel free to reach out to me through any of the methods on my About Me page, or leave a comment in my guestbook!

COVID Summer

I thought this was supposed to be over. The vaccine would show up, everybody would take it, and life would get back to that "new normal" everyone was talking about.

But instead, we're seeing a fourth spike thanks to a brutal combo of the delta variant, vaccine hesitance, anti-vax propaganda, and a general unwillingness to make personal decisions while keeping the general public's health in mind.

Thankfully this hasn't been the worst summer. Last year easily takes the title for worst year ever. I've been able to see friends, regularly go to the climbing gym, and not constantly think about COVID. That was a sorely needed reprieve from the pandemic lock-down restrictions, but now we're sliding back into lock-down mode because this pandemic just isn't over yet.

I don't want to place too much blame on anti-vaxxers. While that group contains a lot of misguided people, there are a select few fraudsters at the root of it all looking to make a buck that should take the real blame. These leaders and their credulous followers are responsible for rising rates of all sorts of preventable infectious diseases, but I think we'd probably still be in the same spot if they didn't exist. The delta variant is brutal. It didn't originate in the US, so a fully vaccinated population wouldn't have stopped it from mutating. Sure, we'd not be facing shortages of ICU and hospital beds had more people gotten the vaccine, but we would likely be facing the similar restrictions that are being put back in place right now to prevent community spread.

Despite all my complaining, I'm pretty lucky. I'm in Washington, where the populace generally values scientific evidence and don't have a governor who is actively working to kill people (like the ones in Florida or Texas). The restrictions here amount to "wear a mask in public" and "please get the vaccine if you haven't yet". Seventy percent of my county is vaccinated, and while we have substantial community transmission right now, it's nowhere near other parts of the US or the world in general.

But I'm scared for the winter. If we get another spike like last year it's going to be the worst one yet. Delta is nasty, and unless something changes we will very likely have to go back to general lock-downs in order to save lives.

Lock-downs suck, as necessary as they may be. My mental health still hasn't rebounded from the trauma inflicted by the isolation and uncertainty of 2020.

Here's hoping the vaccine holds up over the long term so that me and my vaccinated friends and family can try to live some semblance of a normal life, but I'm mentally preparing for the worst.

The Future of the Web: Why It Doesn't Have to Be JavaScript

I am a professional web developer. I use JavaScript on a daily basis, but to be honest I harbor a bit of hate for the language. Don't get me wrong, it does its job and does it well enough, but... there's a reason TypeScript exists.

Despite its glaring flaws, JavaScript is currently the most widely used programming language in the world. JavaScript's stratospheric growth is largely driven by the growth of the Internet and web technologies. And while JavaScript exists on the server, it was born for the web. For decades it's been the primary way to write websites and that won't be dramatically changing anytime soon.

However, the future is on the horizon. WebAssembly (WASM) is a technology being developed as a new type of bytecode meant to run in web browsers. While WASM is relatively rare to see in the wider programming world right now, it has been supported in modern browsers for years.

Do you know what this means?

We're free.

Free from being forced to use JavaScript, a language thrown together in 8 days with some of the most confounding behaviors I've ever encountered in my years of programming.

So what do we do with all that freedom?

Work with a better language!

WASM is likely supported by your favorite language, and frameworks and tools for building web apps are being created and refined every single day. So the next time you need to build a website, give your technology selection a second thought.

It doesn't have to be JavaScript.

WASM + Rust

My favorite WASM-supported language is Rust (which you already know if you've ever had a conversation about programming with me). During the pandemic while I had nothing better to do with my free time, I read The Rust Book and fell in love with its thoughtful design and developer experience. I enjoy it so much that it's my goal to someday work with Rust professionally.

However, the web development ecosystem still needs a little more growth so it will be a bit longer before I get paid to write a web app in Rust. Other languages face the same barrier, but exciting projects like Yew (Rust) and Blazor (C#) are getting better each day.


Recently I decided to put WASM to the test with a serious effort to build a website completely in Rust, doing my best to select tooling and frameworks that replicate what I do with JavaScript/TypeScript during my day job.

The result is Dicebag! I regularly play Dungeons & Dragons and haven't been happy with the online tools my group and I have used, so I'm building tools that will help us have a better experience. As of this writing, it's an ugly, non-interactive Character Sheet, but it gets a tad bit better every time I work on it. If you're curious at checking out the code hop on over to the repository on GitHub. Contributions are more than welcome!

Despite the site not being very fancy, I am very happy with the progress so far regarding the tooling to facilitate development. Here's a short list of each framework or tool I'm using with its equivalent in JavaScript land (where applicable):

  • Trunk replaces Webpack
  • Yew replaces React
  • Rust-specific GitHub CI/CD actions

So far I've really enjoyed the experience with the tooling. None of them have reached version 1.0 at this point, but things are functional and you can produce a complete app with them. I'm sure I'll run into more issues as the site becomes more complex, but the basics are there!

My goal with Dicebag is to provide tools like character sheets, equipment and spell management, custom views to facilitate gameplay by presenting contextually relevant choices, a DM encounter builder, a dice roller, and more. It should be perfectly usable whether you're the only one using it in your group or if everybody is.

In addition, making this site a success will prove out the technology and give me a story to tell the next time I try to convince my co-workers to choose Rust on their next project. Plus, finding the pain-points allows me to contribute to the ecosystem's development by opening issues on GitHub or even contribute code to make the tools better.

We'll see where this project goes, but I'm excited!

Someday I'll never have to write JavaScript again.


I got my second poke yesterday!

A few hours after getting my second dose of the COVID-19 vaccine, I was very tired and took a five hour nap, waking up just in time to go to bed. Unfortunately, I woke up in the middle of the night soaked in sweat with a pounding headache and a variety of bad dreams marching through my brain.

It was an awful night, but I eventually got back to sleep and woke up at 10 A.M. feeling great. The next day was filled with dog park adventures, cooking delicious food, reading books, and playing video games.

Totally worth it.

Trading a night of weird dreams and restless sleep for catching COVID-19 is an excellent trade.

If you haven't gotten your vaccine yet, please do! It will protect you and others from an awful and potentially fatal sickness. The people in my life who caught COVID-19 had an awful time for weeks dealing with its effects.

Vaccines are safe and effective. I consider it a part of my civic duty and am proud to have done my part.

Let's play board games at my place soon, y'all!

First Dose of COVID-19 Vaccine!

I got my first poke last weekend. Next one is on May 8th!

My life is about to become very different, very soon. I can't wait!

Go get your vaccine folks! It's a game changer. Life won't be back to "normal" (or whatever new normal we end up with) for quite a while, but being able to hang out with friends indoors playing board games or D&D will be an incredibly welcome change.

A Year of Pandemic Life

It's been a whole year. One that feels like a lifetime.

A year ago I left my office at work for the very last time. I expected to be back in a couple months, but those months dragged on. I got a pay cut, which spurred me to find a new job. And even if I hadn't changed jobs, I still would not have revisited my old desk to this day.

Worldwide tragedies have a way of shaking things up, and I'm sure others have felt the whiplash of well-laid plans being abandoned and replaced with activities that were incomprehensible a year ago.

I had no plans on leaving the company I worked at for 6 years last March. I had no plans on my pay being dramatically cut. I had no plans to go live with my parents to save some money. I had no plans to build a home office. I had no plans on adopting four plants. I had no plans on reading over 50 books in a single year. I had no plans to learn how to live in solitude.

But a year of a pandemic burning through the world will do strange things to plans.

Thankfully, humans are incredibly adaptable. Our current quarantine setup here in Seattle now gives me the same feelings of normality that I had a year ago. Our hedonistic treadmills largely keep us sane even when the world has gone to hell.

There's a light at the end of this year of darkness. Vaccines are being distributed in the US faster than I ever imagined. I fully expect to be vaccinated by the end of May! Then life will start to get back to the "new normal" that we'll have for the next few years. Until the world is vaccinated, we're going to be dealing with COVID restrictions both here and abroad for quite a while, unfortunately.

But getting together with friends and family won't be dangerous anymore. I won't need to allocate my time to see different friends in 2-week increments. I won't have to wear a mask when I sit on my friend's couch while we catch up with each other. I won't have to constantly cross the street while walking my dog to avoid other people on the sidewalk. So many things will change with the vaccine, and those changes are sorely welcome.

Even though we'll be wearing masks for months more and we'll all still have the pandemic on our minds, the small changes that vaccines enable will be more valuable than any international trip. I still desperately want to travel, especially after spending some of my health being on travel projects as a consultant where I built up plenty of airline miles. Those trips will come with time...

The world will be strange for quite a while longer, but drastic changes are coming with the vaccine.

I can't wait to get poked!

Farewell Flash!

Today, Mozilla shipped Firefox 85, in which they completely ripped out Adobe Flash functionality. And while Google hasn't quite shipped their Flash-less Chrome release yet, I don't care because Chrome is essentially Google-branded spyware that has no business being on my machines. So, in my world, Flash is dead. 💥💀⚰️

For those of you who didn't grow up in the early '00s playing online Flash games or watching Flash cartoons, Adobe Flash was an easy-to-use technology for building interactive content that could run in a web browser. This was back when the Internet was just finding its feet and technological standards had not yet been agreed upon. Adobe, makers of Photoshop, was one of many companies that created their own tools that far surpassed the abilities of the early Internet.

The content for websites like Homestar Runner and Newgrounds, among many others, were all built using Flash. But internet browsers didn't understand how to display Flash content, which meant users had to download an Adobe Flash plugin.

Once the browser had the plugin installed, Flash sites "just worked". You'd occasionally get pop ups on your computer to update the Flash plugin occasionally, but that was a small price to pay to watch Trogdor burninate the countryside!

Unfortunately, downloading all those plugins and updates gave malicious actors plenty of opportunities to write viruses and take control of another person's computer. Many folks dismissed those pesky update notifications, and millions of computers were left vulnerable because they had outdated versions of Flash. It was a security hole that was frankly not worth having just to watch a couple cartoons or have fancy interactive websites.

Thankfully, the IT community worked together to create web standards that enabled the same sort of functionality that Flash provided, but using a single approach that everyone agreed to follow. If you've seen technology acronyms like HTML5, it's that kind of stuff that helped killed Flash. After we built the modern Internet, Flash really didn't have much of a purpose. And In 2017 Adobe announced Flash would die at the end of 2020.

Spoiler alert: we made it through 2020!

I like to think Flash sacrificed itself to appease whatever apocalyptic gods were lurking among us last year and they apparently deemed it an acceptable enough offering that we get at least one more year. 🤞🏻

But as wonderful and amazing as Flash was in its prime, technology marches onward.

That said...

Flash has been reborn using a really cool piece of technology called Ruffle so that we can continue to enjoy Teen Girl Squad cartoons until the heat death of the universe.

And yes, it's written in Rust! 🦀

But the important thing is that nobody will be writing new Flash programs, outside of hobbyists or any companies without the forsight to switch to modern technology.

Fareware Flash. The cartoons and websites created by you were an incredible part of Internet history.

You will not be forgotten!


Joe Biden is officially the 46th President of the United States!

The inauguration was vastly different than any we've seen before. The new administration did the smart thing and limited attendance, both because of the pandemic and the threat of violence from those who participated in the January 6th violent insurrection/most incompetent coup attempt ever.

I was fully expecting something to happen, but was immensely relieved when President Biden walked back up those stairs into the relative safety of the Capitol building.

Today is a good day. The weight of four years of stress from what will likely go down as one of the worst presidential terms in history has evaporated. A burden lifted from my shoulders.

No longer will I be upset at my president for enacting harmful, racist, neo-liberal, classist policies.

Now I will be upset at my president for enacting slightly-less-harmful neo-liberal, classist policies! What a wonderful change lol

But seriously. I think Biden has the potential to become one of the most transformational presidents in modern history. He wants to address the pandemic. He wants to start a clean energy transformation of our economy. And he wants to unite instead of divide.

That's a very good start, and while Biden was far from my first choice of presidential nominee I'm actually looking forward to the next four years.

Let's do this.

My 2021 Government Action Wishlist

After the unlikely, but very welcome, results of the Georgia special elections, new opportunities abound. It's been ages since we've had a unified Democratic government that will now have the ability to get things done!

This is my wishlist of everything I want to see happen before 2022, when the GOP gets its next shot at taking back power. So many of these things are pie-in-the-sky given the type of people currently in power, but I am optimistic that some will happen or we'll at least make progress towards others.

Now, let's check out everything I want to see happen to make the United States the incredible nation we have the potential to become:


  • Remove all gas and oil subsidies
  • Use the gas and oil subsidies to supercharge green energy initiatives
  • Create a federal job guarantee with unionized jobs building green energy infrastructure
  • Make fracking illegal
  • Stop any future oil extraction sites from being built anywhere in the United States
  • Dismantle pipelines across the nation


  • Build high-speed rail connecting every major population center
  • Nationalize at least one airline and use it to experiment with making air travel greener
  • Subsidize public transportation with incentives for cities to build out multi-modal transit networks
  • Subsidize electric vehicle purchases
  • Strengthen unions so workers who can work from home have the power to do so


  • Remove cannabis as a Schedule One drug and immediately release all people in prison with cannabis-related charges
  • Fully legalize cannabis and tax it
  • Pump those cannabis taxes into our education or health system
  • Decriminalize all drug use and possession
  • Create safe injection sites with treatment programs to help people get out of their addictions


  • Impose a progressive tax rate on all forms of income, with the upper bounds in the 90% range for the obscenely rich
  • Bring back a strong inheritance tax
  • Implement a carbon tax


  • Make public universities tuition-free
  • Forgive all federal student debt
  • Pay collegiate athletes and separate the financial destinies of universities from sports
  • Create more trade schools and stop encouraging everyone to attend a traditional university


  • Create a single payer system
  • Write laws that require the portion that employers used to pay to insurers to be given to the employee as wages (to be taxed) so that companies don't just pocket that money
  • Built out a redundant hospital system so the shock of future pandemics and other nation-threatening health issues can more easily be handled

Food and Water

  • Prohibit factory farming
  • Ban mono-culture farming practices and start using restorative and sustainable farming techniques
  • Ban private companies from selling bottled water and profiting off of public water supplies
  • Build out public water sources, including fixing the water systems of Flint and other cities


  • Make the Internet a public utility
  • Break up big tech into separate companies, especially Amazon and Google
  • Provide more funding to government scientific institutes
  • Create strong privacy rights laws for Internet users
  • Build out a federal Government as a Service (GaaS) platform to create an open source platform of tools for running a state
  • Create a public cloud used to run government technology and provide it as a service to citizens, complete with open source, privacy respecting tools


  • Switch to a ranked choice voting system
  • Abolish the Electoral College so the presidency would always reflect the will of the American people
  • Expand the House of Representatives to reflect the growth of the nation since we froze the number in place
  • Put an end to American imperialism by adding Puerto Rico, American Samoa, Guam, U.S. Virgin Islands, and Northern Mariana Islands as states or give them independence


  • Negotiate trade deals that require a basic level of human rights and worker protections with our trading partners
  • Provide tax breaks to corporations that stay within the United States, or add a tax for being a multi-national corporation
  • Open up borders so that people can move just as easily as goods


  • Take possession of empty or infrequently-used housing and give it to the homeless
  • Add a tax to any remaining housing being used as an investment vehicle instead of a domicile
  • Strengthen union power and create unions for new sectors of the economy, especially in the technology industry
  • Create a substantial tax on multi-national companies stashing their money in tax havens
  • Provide a universal basic income (using the taxes on the ultra-wealthy)
  • Do major trust busting on Big Tech, media conglomerates, Internet service providers, and the many other industries that have consolidated over the last few decades

Now, I'm sure I've missed many other things that I would love to see happen, but this is what came to mind in an evening of writing. As you can see, I don't really fit in either political party, but utopian ideation is needed in order to create a new world. Everything in politics must first be birthed as an idea before it can be enacted physically, so this is my little contribution to The Discourse.

If you agree with a lot of this stuff, say hi! If you don't agree, say hi too and let me know why something won't work, because many of these ideas need polishing in order to actually happen. And maybe go write your own list! It's a good way to start building a political platform if you ever decide to run for office!

Democracy Survives

Wow, what a day.

On January 6th, insurrectionists stormed the US Capitol building as Congress was certifying the results of the 2020 presidential election. This came after Trump encouraged his fanatics to march to the Capitol in an attempt to overthrow democracy.

The last time the Capitol was invaded was during the War of 1812, but this is the first time that traitorous flags were flown inside. They brought in Confederate and Trump flags, and I even saw a Mormon waving "The Title of Liberty" (a nationalistic rallying call created by a military general named Moroni, a character from the Book of Mormon).

These domestic terrorists stole government property, invaded the individual offices of Senators and House members, caused Congress to go into hiding in fear of their safety, and embarrassed us as a nation in front of the entire world.

And despite all this, the police response to a literal coup d'état stands in stark contrast to the BLM marches earlier this year. It's a damning indictment of the racism built into our system of policing. There are even photos of officers taking selfies with the terrorists. Only 15 or so people were even arrested today in DC.

But if you march peacefully demanding equal treatment under the law, you get a massive show of force, complete with police brutality.

Over 100 Republican members of Congress supported Trump's call to question the results of an election based on absolutely no evidence of fraud. The Grand Old Party has completed its transformation into the party of Trump, and it must be held accountable for what it's done to our nation. Ted Cruz, Tom Cotton (I still can't get over how his name would be considered too on the nose for a fictional racist... Truth really is stranger than fiction), and the other 12 Senators and 121 members of the House who have entertained Trump's failed coup should be expelled from Congress, just as we expelled those who supported the Confederacy back in the day.

I never thought I'd say anything like that, but damn, we live in extraordinary times.

What Trump did today is worthy of impeachment. Articles are already being drawn up.

What Trump did today is worthy of invoking the 25th Amendment. Discussions are already being had in the Cabinet.

And yet, I have little hope that either of those appropriate reactions to what will go down as the slowest, most incompetent coup d'état will happen in the last two weeks of what will surely be known as the worst US Presidency ever.

The next 13 days will be quite interesting. We're not completely out of this until Biden is sworn in as President. Keep your eyes peeled. You're (hopefully) not likely to see such insanity in US politics ever again, but there is still time for Trump to continue his hissy fit and maybe cause even more chaos.

But I think we've seen the worst after today. It looks like our democracy will hold. Congress reconvened and finished certifying the votes.

Joe Biden will be the next President, and while he was far from my first choice, I couldn't be happier that the party that birthed this coup d'état no longer is in power to continue fucking over our nation.

Bye 2020

Phew, we made it. Done with the worst year ever!

I'm decently confident things can't get worse. Trump's loss and the coming rollout of the COVID-19 vaccine will remove two of the most immediate threats we face. I'm hoping the Biden administration hits the ground running and is able to fix a lot of the issues we have now around inequality, climate change, student loans, homelessness, etc.

Yeah... that's a grab bag of wishes, especially if we lose the Senate. But I'm holding onto that hope for now because it makes me feel happy, and sometimes you just gotta do what makes you happy!

It's also been a while since I've posted. All the stress from the election, pandemic, adjusting to a new job, and general laziness has gotten to me, but I'm hoping to write a bit more in 2021, especially around technical topics.

Here's to a much better year than the last!


In the United States, the general election is coming up in a couple weeks. While every election seems like "the most important ever", this one is particularly noteworthy. We're in the middle of a global pandemic, climate change is creeping closer, and economic inequality abounds.

American democracy is under attack. Voter participation has been incredibly low over the last couple decades, and blatant voter suppression tactics are deployed regularly, like limiting the number of ballot drop boxes or polling places to make it difficult to cast a ballot.

Despite our historic lack of participation, early voting levels are drastically outpacing past elections!

While our country faces a deep political divide, I do think we can all celebrate the fact that more citizens in this election are exercising their democratic right to vote. High levels of voter participation theoretically leads to representatives being elected who more closely mirror the desires of the populace. And it's my hope that high turnout will lead to many broadly popular policies (weed decriminalization, infrastructure and healthcare improvements, progressive taxation reform, etc.) finally being enacted by the politicians in D.C.

I know many people are unhappy with the choice for President. But there are far more elections on the ballot than a single office. Even if your favorite presidential choice doesn't win office, you can still have an impact on your local and state races, who are arguably more integral to making things happen that you'll notice in your day-to-day life.

So go get educated. Read voters guides, newspaper and union endorsements, the candidates platform, and any other reliable information you can find. Then cast your vote for the people who are closest to building the world you dream of.

The last four years have been a mess for me. Voting for Joe Biden, despite him being one of my last choices, was an incredible opportunity for me to be the change I wish to see in the world. I've felt a bit powerless following politics over the last few years. Submitting my ballot felt amazing. I did my bit for building a better world.

Please, do your bit too!

If you're new to voting or need a bit of help, is a fantastic resource to help you exercise your civic duty and one of the most important democratic rights you have!

Let's smash turnout records. Let's get the will of the people heard and give the next government (regardless of who wins) a clear mandate to enact their agenda and (ideally) make the world a better place.