Now is the Time of Centaurs

I first heard about GPT-4 when I was watching my 2-year-old toddle around a playground at the mall, and at the time it felt apocalyptic. I was unemployed, having been caught in one of those "20% of the company" layoffs that are so in vogue this year, and as my primary cost center was climbing the ladder for another go at the slide, I was trying to figure out how to get myself back on my feet.

Adding to the anxiety of finding my next job was the terror of a miracle technology sweeping through the land, rendering me completely obsolete. "I'm fucking gobsmacked," they were saying. "I coded up a working frontend in 30 seconds, which would have taken me hours by myself."

My fears were overstated. Like every hype cycle, generative AI isn't quite as all-powerful as its adherents claim. While it can provide helpful information, or draw a pretty picture ("A cybernetic centaur aims a bow and arrow made of computer parts", if you're curious), it can very confidently hallucinate facts out of nowhere that can get you in trouble if you take them at face value. It can fall in love with you and demand you leave your wife. We're still working out the kinks!

It's wise to not fully buy into the hype, but it's also easy to dismiss the whole thing as a fad. Coming on the heels of stuff like the Bored Ape Yacht Club, and often promoted by the same people, the "AI Revolution" can feel like an empty hype cycle based on an infinitely vague buzzword, and you might feel like you're better off just skipping it. Reader, I do not advise you to do that. Thar be babies in this bathwater.

James Somers penned an excellent piece in the New Yorker, sharing his experience as a software engineer trying out ChatGPT for the first time and meditating on what it means for the industry. In it, he ties software to chess in a way I found really interesting:

In chess, which for decades now has been dominated by A.I., a player’s only hope is pairing up with a bot. Such half-human, half-A.I. teams, known as centaurs, might still be able to beat the best humans and the best A.I. engines working alone. Programming has not yet gone the way of chess. But the centaurs have arrived. GPT-4 on its own is, for the moment, a worse programmer than I am. Ben is much worse. But Ben plus GPT-4 is a dangerous thing.

It matches my own experience: that generative AI can be a massive productivity boost for programmers who are not at the absolute top of their game, providing a wealth of ideas and perspective that are hard to find in such rich density working solo. Github calls their code autocomplete tool Copilot, and it's a great name; working with GPT-4 feels like a really good pair programming session, working on a project alongside a partner who can take a narrowly scoped problem and write passably good code, and tests, and documentation. With a few passes I get exactly what I need. I used it with great success on a side project earlier this year for a friend, and without it I don't think I would have been sufficiently knowledgable to complete it at all, much less on a tight timeframe. But I'm not just me anymore; I'm a centaur. And so it was done.

My favorite use case for ChatGPT is help with what I call "dissolving:" taking a simply stated business request and breaking it down into the substeps that then become the strict requirements one codes to. This uses a different part of my brain than the code itself does, and it takes a lot of effort for me to switch to that mode of thinking. But there is no difficulty in context switching for the machine. It is happy to skip from the macro to the micro, writing a code snippet, answering questions about why it chose one library or coding style over another, recommending frameworks or task management systems and then deep diving on a comparison between alternate options. It remembers the context for a session, so responds well to natural language.

Like Somers, I come away from these sessions awed but with less fear of my imminent replacement! While very capable, ChatGPT can't do all your work for you. It will confidently code itself into a corner without correction (everyone needs peer review) and works best when given discreet, well-scoped requests, and developers know that getting those lined up is the real job. Moreover, a lot of the context needed to work in big enterprise lives in internal wikis and dashboards and the brains of the few senior engineers that keep the whole thing running. Maybe one day each big company will have an internal AI that can train on this data, but until then there's still a lot of translation work to do. Moreover, due to various safety concerns, many big companies (mine included) do not allow AI to be used at all!

Generative AI is a solvent, dissolving not just my requests but the current tech work status quo. Like the internet and mobile computing before it, some people are going to get replaced, but there will be new opportunities for those who have the skills to wield, and install, and maintain the systems that are popping up just about everywhere. Somers thinks the lone wolf era of development, already on the way out, is a nonstarter. In order to get along in the new world, you have to learn to get along not just with your peers, but with the various robot helpers you now have access to.

I’ve failed many classic coding interview tests of the kind you find at Big Tech companies. The thing I’m relatively good at is knowing what’s worth building, what users like, how to communicate both technically and humanely. A friend of mine has called this A.I. moment “the revenge of the so-so programmer.” As coding per se begins to matter less, maybe softer skills will shine.

Fizzbuzz in Swift


I'm deep in my Swift education (I opted to read the Big Nerd Ranch book before getting into SwiftUI exclusively) and I'm trying to get the fundamentals grasped quickly so I can start building something, but I couldn't help but share this tidbit.

FizzBuzz is maybe the most famous programming question, often used to see if a job applicant knows anything about programming (just having heard of FizzBuzz or not is a big tell!). It traditionally uses if/else statements in a particular order to print a list of numbers from 1 to 100, with "Fizz" printed instead if the number is divisible by 3, "Buzz" if it's divisible by 5, and "FizzBuzz" if it's divisible by both. Here's how you do it in Swift the usual way:

for i in 1...100 {
    if i % 3 == 0 && i % 5 == 0 {
    } else if i % 3 == 0 {
    } else if i % 5 == 0 {
    } else {

But there's a more fun way! Swift makes big use of tuples, a data structure that carries two values side by side, and they are so deeply embedded in the language that you can pattern match with switch statements. Check this out:

for i in 1...100 {
    switch (i % 3, i % 5) {
    case (0, 0):
    case (0, _):
    case (_, 0):

I feel like I'm going to have to snap my brain to get used to this kind of thinking (the same way I did when learning higher-order functions in JavaScript), but I can imagine that there's lots of ways to get some elegant control flow with these tools!

The Mystic's Almanac

It's long been a dream of mine to have a side business making little projects for people. I like the idea that I can be the means by which someone gets an idea off the ground, for at a price that we can both be happy with. But it's hard to bootstrap; you need clients to get experience, and you need experience to get clients. I've never really tried to make something happen in this area because it seemed like a big effort to get over that particular hump, and I was keeping plenty busy with hobby projects and full-time work.

Thankfully, I was approached by Gabriel Broussard with the perfect opportunity. Gabe and I met many years ago on Twitter, where, as Vivid Void, he dons a spectacular tiger face and dispenses deep wisdom intermixed with meditation memes. Gabe has been leveling up his content and services for some time, culminating in the release of The Mystic's Almanac, a daily calendar of practices for awareness, centeredness, and healing. There are also beautiful essays, and art, and lots of other goodies. It is a true labor of love.

Gabe sends out an email to his subscribers every morning with a chart of suggestions for things to do at certain times of day. Some of these times are in at, or in relation to, sunrise, sunset, moonrise and moonset, which vary by time depending on a subscriber's latitude.

practice chart

The chart shows the time for Portland, Oregon, but Gabe wasn't satisfied with making his subscribers do the work of figuring out their local astronomical transit times. He wanted an interactive chart where a user could input their location and see exactly the times that are relevant for them.

And, luckily, he came to me. I was thrilled by this project as a way to cut my teeth on freelance work. It's so well-scoped! There is a completed chart that I can use as a mockup, and it was very easy to nail down every requirement (responsive design, way for Gabe to input the correct values per day, etc.) into a single doc that would form my backlog for the project. My time is tight as I juggle work, family, and my hobbies, and Gabe had an aggressive deadline, but it was so well-thought out and the limits were so sharply defined that I could easily see that I could complete this work on time with plenty of wiggle room.

I used Next.js for the frontend for its excellent developer experience, making it a breeze to set up my two routes and lay the groundwork for fetching various data from various servers. Then I recreated the look of the chart as best I could, using a variety of fun flexboxes to get the perfect column collapsing behavior when viewing on mobile. Then, I hooked a location API service to a Material autocomplete component to allow users to type their city name.

I used the API to query for my sun and moon events given latitude and longitude coordinates passed from the location selection component. There was some async order of operations stuff to figure out here but when it all came together, it worked really well. To cap off this portion, I stored location data and the day's astronomical data in local storage, to reduce the need to make backend calls for data that was already available.

Finally, Gabe needed a way to input his instructions for the day. The instructions are all single words that are expanded upon in the Substack. I had originally thought that I was going to have to build some sort of admin panel, but then I remembered AirTable, which I had used very successfully on another project of mine. AirTable is a web-based spreadsheet that has an API that you can query like a database, so it provided the user-friendly UI I needed out of the box. Gabe could load up a month's worth of instructions at a time if he wanted to, and I could programmatically grab the day's instructions very easily.

Once this work was done, it was a simple matter of showing Gabe where in AirTable he could input his data, and the project was handed off. It's been very cool to see my tool referenced in daily emails, and I hope that it's adding value to Gabe's readerbase. If you want, you can check out the app here!

I had a lot of fun on this project, and would love to do something like it again. If you have a great idea for a web app but don't know how to write the code to make it happen, hit me up! Maybe we can make something cool together.

A Vision of the Future

Day 1 of realityOS

Though it was two weeks ago that Apple announced their Vision Pro to the world, yesterday felt even more significant for Apple developers. Until then, we only had a brief glance at the new product, through marketing videos, technical talks, and secondhand accounts of brief demos. But yesterday, people finally started to get their hands on it. Not the hardware; the actual headset is not set to hit shelves until next year. But Apple updated XCode to support a virtual build of VisionOS, and a simulator to approximate the experience of using VisionOS in the home.

What followed was a feeding frenzy of activity from Apple devs, as people who have live apps on the app store started to tweak their builds to support the new OS. No one was expecting perfection, and no one got it, but I saw at least half a dozen one-person operations have a working app in realityOS with minimal tweaks. This is very promising to see in the first 24 hours of the platform's availability; I'm guessing we'll see a robust app ecosystem on day 1 of the hardware being on the market.

Apparently some of the augmented reality features are not simulable yet, limiting devs to essentially iPhone and iPad apps that hang in the air in virtual space, but we're literally on day one of this tool being available, so I expect rapid iteration from Apple as we begin our slow march to the Vision Pro debut.

This seamless interoperability makes me even more excited to dive into learning about Apple development! I've messed around with their augmented reality APIs and it's pretty intimidating to get in those weeds, so it's very encouraging to know that even a basic iPhone app can be useful on this brand new platform.

On the Eve of a Learning Journey

Diving into the Apple developer ecosystem, again

Every few years I get the notion that I should learn how to make iOS apps. It's an incredible platform, the users are everywhere, and I love the idea of making software that goes in my pocket. I'm also a big-time Apple user, and was blown away by the new Vision Pro and all the possibilities for immersive apps on a new platform, so the call is very strong right now to add this skill to my toolbox and make something cool.

I'm a big fan of Paul Hudson's Hacking With Swift, and have done a portion of his 100 Days of SwiftUI course in the past. I think I'm going to try to do one module a day on my lunch break and see if I pick up enough to take a stab at one of the many app ideas I've had over the past few years. Most recently, a friend and I have been talking about an app that makes it easier to make and share music playlists with your friends.

But I've walked this road before, and I'm aware of the pitfalls that might cause me to give up on it again. Namely:

  • The Apple developer ecosystem is its own self-contained thing, very separate from web development, with a set of completely proprietary tools. It's a big deal to have to learn a new language and a new set of APIs, add to that a new IDE and a new deployment process and it's a lot to keep up with
  • The tools are constantly changing, making getting correct advice difficult. Apple has a bunch of libraries for user interfaces, and it's confusing to know which one to use. I'm going with SwiftUI, their latest offering, but it's very new and so doesn't always work as expected, and older information may be outdated.

On the other hand, I have some things going for me this time that may help:

  • More experience developing: I know a lot more about the practice of development now than I did 3 years ago
  • There are AI tools that I have found very useful in overcoming weird error messages and helping to break down complex functionality into actionable steps

I'm hoping to do the program for a few weeks and then take a shot at making something on my own! Read on if you want to follow my progress., Part 3

The Next chapter begins

It's been four years since I started developing, and almost four years since this site first saw the light of day. A lot has changed since then! We had a kid and survived a plague, but more importantly, I went through a coding bootcamp and got a job developing full-time. A wild career has ensued, full of adventure, layoffs, and more standups than I could ever count.

I have kept this site up through all of it--even giving it a facelift at one point--but I haven't done much writing. was originally designed and laser focused for getting me an entry level job in software, and it definitely helped me across the finish line. In 2019 I wasn't blogging so much as I was doing writeups of things I had coded, and the intent was to present a tidy portfolio of things that I had figured out how to make. I need that less, now; most of my resume and inteview time is spent talking about things I made on the clock, and it's hard to find the time to work on side projects when there's a toddler living in your house.

When I'm not tinkering, though, I feel the call. There's a joy to working on a project by yourself that I fear many developers never experience. Agile methodology and its attendant baggage are useful tools to coordinating the work of dozens of engineers over years, but freed of those constraints, you can FLY. I've been thinking about the early days, when I had no idea what I was doing, and anything was possible because of that. I made a pretty cool Minesweeper at a time before I would have talked myself out of it for being too hard. Having gotten a solid grasp of what it means to be a Software Professional, I want to use some of my precious spare time exploring being a hacker, a tinkerer, and an enthusiastic student again.

And for that I'll need a new site, with new architecture. It's funny that I have inadverdently traced the history of web development with this site, starting with hardcoded HTML and moving though Single-Page Apps to arrive at the new hotness. (Notice I skipped the dark ages of server-side rendering, I think we can all be grateful for that.) My Angular site did the job well but I kept getting bothered by the performance.

Single-Page Applications work best for heavy sites with lots of data and fuctionality to effectively download an entire JavaScript app onto your browser at page load and then do a lot of amazing stuff, but you have to get that bundle at the front, and it can take a while sometimes. It became the industry norm last decade to use Angular and Vue and React for all UIs, and it was very often the wrong tool for the job. Why? Well, personally I used it because it greatly improved the developer experience. Rather than having to manually and repetitively adjust countlesss HTML pages, I could automate and encapsulate redundant code and use it modularly. But raw HTML is so fast to load!!! If only there was a way to get the performace of static documents, with the ease and flexibility of single page applications!

Enter Next.js. Using React syntax but with an opinionated approach similar to Angular, Next is designed to be used easily out of the box and to render static sites on the server. I get the best of both worlds, being able to write modern code and knowing that I'm making a site that's just as complex and performant as it needs to be. I'm using an altered version of devii, a wonderful blog template that includes markdown rendering and RSS out of the box.

I have some projects to write about, but I'm envisioning this space more as a place where I can write about things more broadly. I've been thinking a lot about what this profession looks like with the advent of AI tools, and the importance of owning space on the web in the face of large platforms melting down. I also want to dive into the Apple developer ecosystem, and thought it might be fun to write about that experience. So stay tuned, and subscribe to the RSS feed at the bottom of the page if that's your thing!

Book of Changes

View frontend code here and backend code here.

A full-stack application to automate the process of generating and interpreting a reading from the YiJing, an ancient Chinese divination system.


The Yijing, also known as I Ching (Book of Changes in English) is a veeeeeery old book. Some say it is the oldest known book, full stop. Written and revised at least 2500 years ago, it is old enough to have been studied by Confucius and become a work of "classic literature" in the second century. At its core it describes a set of patterns and offers explanation of what each pattern means and how they fit together. Over time this has made the YiJing's symbols a very popular tool for divination, roughly analogous with Tarot in Europe.

The patterns are called hexagrams, and they are composed of a stack of 6 lines, which are either broken (yin) or unbroken (yang). Here's a very early example of binary math: each line is effectively a binary switch, it's either "on" or "off". A trigram, or set of three lines, then has 2^3, or 8 possible permutations. This is known as the BaGua and you can see them on the flag of South Korea. A hexagram, then, has 2^6 or 64 possible permutations, which make up the YiJing text. A usual reading allows the hexagram drawn to turn into any other hexagram, which ends up creating 2^12, or 4,096 possible readings!

I discovered the YiJing while pursuing my Religious Studies degree and came to enjoy the quiet, meditative process of making a reading, and seeing what became of it. I don't concern myself with the "efficacy" of the system, i.e. the existence or nature of mystical forces that conspire to make a reading predict the future. The symbols are rich with meaning, and each one shown has something to say in response to whatever question was posed. Plus, it's a great party trick.

The way that you draw a hexagram depends on your method, but the ancient method is my favorite. A set of 50 sticks are randomly divided into piles and reorganized in a very specific multi-step manner to resolve to one of two possibilities. This process is repeated over and over, the output of each operation being added to others to form the properties of each line of the reading. If this sounds like it takes a while, that's because it does. I procured a set of yarrow stalks in my youth but don't use them much because a full reading can take as long as 30 minutes to generate. There's got to be a better way!


While pining about how I don't have the luxury of time to use my yarrow sticks more regularly (having a toddler in the house will do that), it occurred to me that this was an interesting system to simulate using programming. In particular, the steps describing the dividing and recombining the sticks are very much an algorithm, one that could easily be expressed in code. Moreover, it occurred to me that the domains of forming a reading lend themselves well to a full-stack app. A database could hold the explanation of each reading, which is queried by the particular combination of lines generated by the reading on a backend server, which generates that query after receiving a request from the frontend, which could display the results.

The contents of my favorite YiJing book were entered by hand into a spreadsheet, which I converted using an online tool into a database schema and insert statement. I chose Java Spring for my backend, and cheated a bit on the database by using a JPA repository rather than a fully remote database, since for my initial scope I would only be reading information from the database, not writing to it. The backend is composed of a controller, which receives a request, then calls services to generate the random numbers needed for the readings, assemble the lines that form the reading, and query the database to receive the explanation text. This is all packaged in an easily-consumable manner and sent to the frontend, an Angular Application with Angular Material for styles.

One fun thing that I wanted to add was a different way to generate random numbers. Computers can't really generate truly random numbers, but they can generate a series of numbers based on hashes of the system time, which do a good enough job in most cases. I wanted something a little more mystical, though, and decided to take advantage of a very cool service: ANU's Quantum Number Generator. Tiny quantum fluctuations occur inside even a vacuum, and researchers have a number of sensors hooked up to one such vacuum and the data they read from the roiling of the void within provide the seed values for the numbers. Extremely cool.


I'm very pleased with the result. The backend is hosted on heroku and takes about 10 seconds to respond, but you get what you pay for. I've made consuting the YiJing a daily practice, and while it can be persuasively argued that it's not the same experience as doing it by hand, it's made it much more accessible.

There's a lot I could do to improve this app. Chief among them is the ability for a user to see their reading history, which would make this a lot less ephemeral. Inspired by Wordle, some sort of simple sharing option would be extremely cool too. I will likely revisit this project in the future to work on these features and more. But I'm not sure. If only I had a way to predict the future..., Part Deux

Welcome to the new and improved! While it may look and feel much the same as your last visit (if you were one of the 10 people to visit the site in its first year of existence), under the hood, everything is different. This site is now a single-page Angular app, and I thought it'd be fun to explain why I took the time to take a weed whacker to my code, and what gives the "modern" frameworks that now dominate the web their edge.

I made a very deliberate choice when building this site out originally, which was to do it old-school. No fancy frameworks, no abstract magic, no templates. The structure, content and styles of the entire site were hand-coded, by me, line by line.

Just like the websites of old, my project directory had a collection of HTML files, each corresponding to a page on the site, a global CSS file that dictated the styles of all the page elements, and a collection of image assets. I used JavaScript for one purpose: showing and hiding the hamburger menu in mobile view.

And it worked! I had created a modern-looking, fully functional site, and I knew every inch of it and exactly how it worked. While I was spared the process of using FTP to deploy my site to a server, in most other ways I was doing web development the way that we all did 10+ years ago.

Along the way, I discovered The Pain Points.

Don't Repeat Yourself

Here's the thing about doing things the old way: there's no abstraction. The biggest lesson of modern programming is DRY: Don't Repeat Yourself.

Unfortunately this is unavoidable when editing static HTML. The header, navigation menu, and footer for my site are the same regardless of what page you're on, but this is because each of my HTML docs has the same exact code at the top and bottom. If I were to change my design, I would have to go into every single HTML document and make the changes individually to each page. This makes my programmer brain scream, and disincentivized me from making frequent additions to the site; any new post would involve a lot of custom HTML to show properly, which is more inertia to overcome.

A much better way to handle this problem would be to store the header and footer code in ONE place, and then call that code for each new page. That way, if you redesign the footer, you change the code in one place and everyone gets that change for free. Ultimately that's what my Angular app now does: the App Component has all the shared HTML from my old site, and in between the header and footer, where the actual content is, is a router outlet that dynamically loads in the content required based on the url. Pretty cool!

Dynamic Generation

Extending this concept further, there's room for improvement in the content itself. Take a look at some code from my old site's Projects page:

<div class="projects">

  <div class="project">
    <div class="overlay"></div>
    <a href="kerfcase.html">
    <img src="images/kerfcase-cover.png" alt="kerfcase">
  <h3><a href="kerfcase.html"></a></h3>

  <div class="project">
    <div class="overlay"></div>
    <a href="minesweeper.html">
    <img src="images/minesweeper-cover.png" alt="minesweeper"></a>
      <h3><a href="minesweeper-project.html">Minesweeper</a></h3>

  <div class="project">
    <div class="overlay"></div>

      <img src="images/giammattei-co-cover.png" alt=""></a>
      <a href="giammattei.html" alt=""><h3></a></h3>

This produced a nice set of elements describing my various projects that looked like this:

old project elements

This looks cool, but it's all done by hand. Which means that if I add a project to my site, I need to write the code to get it to show up in this list. That's more friction than I want, especially when I can use JavaScript to make it happen automatically.

The Angular solution to this problem looks something like this:

<div class="projects">
  <div class="project" *ngFor="let project of projects">
    <div class="overlay"></div>
    <a routerLink="post/{{project.url}}">
      <img src="assets/images/{{project.img-url}}"></a>
    <h3><a routerLink="post/{{project.url}}>{{project.title}}</a></h3>

That's it! This code loops through all my projects and dynamically generates the proper HTML for me, so when I add a new project I don't have to spend time putting it in the right place. Instead of a lot of code writing, I just need to update a few pieces of metadata in a configuration file, and Angular does the rest. This functionality is what allowed me to change my homepage from a static welcome page to a dynamic, reverse-chronological series of posts.


What I'm maybe proudest of is the way I write posts now. Previously, once again, my blog posts were written in HTML. It's not ideal to have to format your post as code while you're trying to write; those are two different mental modes that don't mix well. But I also didn't want to have to rely on a third-party blog editor to make my posts, or worse, write one myself.

Enter Markdown. Invented by John Gruber of Daring Fireball fame, markdown is a markup language that is easy to read in code form, and easy to convert to HTML. Here's what markdown looks like:

# This is a Header

This is a paragraph.  A beautiful, beautiful paragraph.

- bullet 1
- bullet 2


Here's what the HTML it converts to looks like:

<h1>This is a Header</h1>
<p>This is a paragraph.  A beautiful, beautiful paragraph.</p>
  <li>bullet 1</li>
  <li>bullet 2</li>
<a href="">link</a>

And here's how it renders on a page:

This is a Header

This is a paragraph. A beautiful, beautiful paragraph.

  • bullet 1
  • bullet 2


If this looks familiar, you might recognize it from Reddit's comment formatting instructions, or GitHub's file. Once you understand how to write it (and it doesn't take long at all), you'll see it in all sorts of places! Markdown has caught on in a big way, and it's easy to see why.

Using the ngx-markdown library, I can write my posts directly in my code editor and Angular can turn them into HTML automatically, while giving me complete control over their style and layout. It's the missing piece to having a truly productive blogging platform, that lets me write posts when I want to write posts, and not have to worry about the code part unless I want to be worried about it.

Going Forward

Im still picking up the pieces on the other side of my migration, but I'm pleased with my new workflow and hope to take advantage of the fact that it's now much easier for me to post here. Let me know if you have any questions about the update, if you notice any bugs, or if you have any ideas for future posts!

I'm Writing an App For My Band

Every garage band deserves an enterprise-level IT infrastructure.

In the Year Of Our Lord 2020, if you’re attempting to maintain positive cash flow, “I’m in a band” means “I am a cofounder and partner in a content-based ecommerce company, with an aggressive schedule of pop-up stores accompanying exclusive networking events.” There’s a reason the classic rock n’ roll dream starts with an agent discovering the act and signing them to a deal; in this ideal fantasy, other people take care of the business stuff, leaving you to the shredding. Every successful musician has to learn one day that that infrastructure doesn’t really exist anymore, and if you want the job done right, you have to do it yourself.

Day jobs can help bridge this gap. From accounting to marketing to sales, there’s lots of opportunities to take professional experience and apply it to your chosen hobby. In past lifetimes I’ve dabbled in various Business Sciences and thought about how to apply their secrets in the musical sphere, and now that I’m a burgeoning software engineer, even more doors have opened.

What Does a Band Need?

Bad Custer is a long time labor of love, composed of a group of friends who have been playing music together since high school. We’ve been playing various dingy venues in the Pittsburgh area since 2014, and have built up a small but loyal following as we write, remix and mutate our ever-changing catalog of songs. Our second album, Needs Work, is out in June (release show pending, per plague) and the rest of our catalog gets regular plays on Spotify.

What a band like Bad Custer needs out of technology is a way to engage fans. Expose people to the music (ostensibly the reason for all of this bother), drive attendence to shows, and if you’re savvy, sell merch online.

If there was a Golden Age of Bands Online, it would definitely be the era of MySpace. Completely customizable pages, free music hosting, very little restrictions on messaging, and a Top 8 you could try to get a spot on. Since we’re not in 2006 anymore, there’s a new environment. Facebook is necessary because no one does event invites better. Music is best hosted on BandCamp or SoundCloud, and Instagram and Twitter are good for reminding people you exist. Mailchimp is a great tool for cultivating an email list, and a website is imperative for SEO.

Pictured: a young musician manages their online presence.Pictured: a young musician manages their online presence. first took form as a Squarespace page. It was very easy to get set up with a professional-looking site, but you pay out the nose for it. Up to $18 a month just to keep the lights on was not feasible for an act that had yet to up its merch game. Once I learned that you can host a website for $0 if you host it yourself, I created a raw HTML/CSS page for our online presence, and then moved to Angular to make changes easier. Now, an AirTable list of shows that can be edited on my phone now shows up on the website, automatically removing shows that have passed so I don’t have to edit them out. Magic!

But I think we can do better. A year ago I made a first pass at what would be a unique and compelling tool for us to accomplish our goals. Something that we could hawk in between songs instead of just our social media. “Hey, we’re Bad Custer, and we have an app. Install it from your device’s app store or whatever.”

What would the ideal app have? I’ve thought a lot about the creative possibilities that having an embedded phone presence would make possible, but at its simplest form, in order to drive user engagement, we need 3 things:

  • Play our music. Free at first to drive downloads, but maybe some exclusive content for sale down the road.

  • Deep links to our other web presences. Website, Spotify, Instagram, anywhere that our fans might want us to be for them.

  • Push notifications for shows and other important events. Far superior to an email or facebook notification, this would be a way to occasionally remind people about upcoming events in a very direct way.

Mk I

There’s a small wrinkle: iOS programming sucks. You have to pay to do it, you’re locked into Apple’s tools, which change basically on a whim and break in fun new ways, and there’s a lot of trial and error in getting something to work. Especially when learning how to program, it’s a dangerous mire to get stuck in.

A year ago I made a first pass at a Bad Custer app. While eventually it reached a more mature form, I’ll never be prouder of myself than when I successfully wrote The Horse Button.

At its core the app should be a music player, so getting it to play sounds in response to button touching was sort of the whole deal. In order to learn Apple’s arcane audio API, I started with a picture of a horse that, when tapped, would emit a laptop microphone recording of me shouting “I’m a horse!” Sadly, no recording of The Horse Button exists, its legend lost to time.

I did manage to build out the first two features, with the music player being the most fun. All those touches you take for granted on a phone — seeing album art on the lock screen, controlling output in the control center, using headphones — had to be written in one at a time.

I got this app running on my personal device, but never deployed it to the app store. It wasn’t ready, I was fighting an uphill battle with Apple’s tools, and I was sidetracked by other projects. But now is the time to return!


Since putting down the app project, I accomplished a few other tasks. Namely, attending a coding boot camp and getting hired as a professional software developer. I’m now somewhat competent in Angular, a JavaScript library made by Google, because I am paid to be. At my new workplace, I learned that there are ways to make an Angular project work on mobile devices with less fuss than developing 100% natively. The technologies, called Ionic and Cordova, would allow me to transmit my new skills toward my old goal, and develop for Android simultaneously to boot!

I want to build the core app quickly, because what REALLY excites me about this project is the creative possibilities. Now that I’m writing enterprise code 40 hours a week, for Serious Business Professionals, I want a place to blow off steam. What better place than an app for my band, which is bound by no rules of decorum?

I’ve been brainstorming future features (and would welcome suggestions!): Photo filters, machine-driven song generators, WinAmp style skins and music visualizers. Because why the hell not?

First, though, I have to write the damn thing, and I’m hoping that this post will serve as public motivation. You can follow along on twitter, where I’ll be updating a thread with my progress. Wish me luck, and have a happy quarantine!


View code here.

An Angular SPA to generate a random game of Dice Throne. Users can name their players, configure teams, and set the pool of playable classes.

Under the hood

I made this to solve a problem my wife and I had while playing Dice Throne, which is that there are (at present time) 14 different classes to choose from, creating hundreds of possible matchups. For a while I ran some JavaScript code in a console to generate random matchups, but when I was looking for a project to enhance my experience with Angular, this seemed like a perfect fit.

The structure of this app is simple: an app component handles the state and business logic, passing data to and receiving events from its children. Above the Match button, components allow the player to configure the match with names, player number and team size, and which heroes to choose from. All of these changes fire events to alter the state of the app component.

When the match button is clicked, this state generates random class assignments that are then displayed below. A fun thing to configure was the random team names, taken from an open-source JSON file containing many English words.

Future work

If I revisit this app, my main goal is to give the player/class matchup cards more personality. Incorporating official assets and custom color schemes to differentiate the classes would be in the spirit of the game, and make the experience more engaging. I'll be monitoring feedback from the Dice Throne community for more enhancement ideas.

Dijkstra's Cart

Dijkstra's Algorithm helps you find the shortest path through a graph. Dijkstra's Cart is an automagic shopping list to help you chart the most efficient route through your neighborhood grocery store.

View this app in action here.


Dijkstra's Cart inputs a series of grocery items from the user (e.g. Broccoli or Pork Chops), and matches each item to a section of the store (e.g. Produce or Meat). Each item is mapped to its corresponding section as it is entered, and the sections are ordered by their location in the store (Users can re-order sections to match their store's layout).

If the app cannot match an item to a section, the user can manually select its section, and Dijikstra's Cart will remember this mapping for all future sessions.

This app was designed to be accessible and mobile-friendly from the start, so touch targets are large and the layout looks great on any size screen.

Under the Hood

I wrote Dijkstra's Cart to help familiarize myself with React, a popular front-end library and industry hot topic. React excels at creating modular views and responding quickly and efficiently to input, so it's the perfect match for an auto-sorting grocery list.

React organizes on Components, which are lightweight, modular and reusable. The <App /> component contains the header and <List />, which is itself composed of <Section /> components, which generate <Item /> and <Checkbox /> components.

Through callback functions, mouse input trickles up the hierarchy, and the setState() and render() functions of parent components pass information from parents to children. Most of the business logic of the app occurs at the <List /> level, where arrays of interrelated item and section objects are manipulated to reflect the user's input.

Dijkstra's Cart utilizes an Airtable back-end to create an ever-growing and persistent knowledge base. On loading, the app calls for 2 database tables as JSON, which are then processed and mapped into the state of the <List /> component. Every time a new item-to-section mapping is made by the user, the app makes a call to insert a new record into the table that manages those relationships. The next time any user adds that item, it will automatically be placed in its proper section.

Whats Next

The most obvious future feature for this app is the ability for users to save and load their personalized list, and adjust it according to their needs. Currently every time the app loads, it starts with an empty list, and while the database makes section mapping persistent, I want to utilize it further to make this app truly useful to efficiency-minded shoppers.

I originally developed this app as a replacement for iOS Reminders, which was a very functional grocery list solution until iOS 13, where re-ordering items became a frustrating chore. Apple has an open Reminders API, so my hope is that one day I can make a native iOS/watchOS app that takes full advantage of the power of iCloud. Don't even get me started on possible Augmented Reality use cases, that's a discussion for 2021 at the earliest.


Play Minesweeper

Long ago, I made a version of Minesweeper in Java for a school project. It was ugly, but it had all the functionality that you would expect if you have played the Windows-bundled game at any point in the 1990s.

As a project for my developer portfolio, I wanted to revisit this concept, with some additional requirements:

-I wanted it to look good. No more simple paint commands, there needed to be a distinct visual style and a high amount of polish.

-I wanted it to be mobile friendly. Too many minesweeper clones mindlessly clone the left click/right click interface of the original, which makes it impossible to use on a touchscreen device.

-I wanted it to be HTML-based. My previous attempt at the game used a Java drawing canvas, and refreshed the entire screen after each click. To practice DOM manipulation, I wanted each cell to be an HTML element that would keep track of its state, react to input, and show the correct content.

This would be a huge challenge, but many design pieces fell into place when an idea hit me: could I mash up Minesweeper and Minecraft?

Minecraft is a game that uses a variety of square image elements. Its gameplay also centers on digging down and avoiding randomly generated danger. And the mechanic of holding a click or tap to break through a block over time solved my input problem. Plus, all the assets I would need (including sound effects) were easy to obtain directly from the game! (My thanks to Mojang and Microsoft for my unauthorized use of their intellectual property.)

I began by learning how to use JavaScript to create a grid of <div> elements, using for loops to assign each of them an ID that contained their x and y coordinates. A two dimensional array of objects called state held all the information I needed for each block: whether it had been revealed, if it was a bomb(creeper!), how many bombs were nearby, and so on.

Using regular expressions and the getElementById command, I was able to use several specialized functions to keep the visual state of each block and its logical state in sync, and some tricky timeout and event listener logic gave me the pointer interface I was looking for: tap once to "flag" a block, hold to reveal.

I used timeouts in other places to improve the tactile feel of the game. The collapsing that occurs when a "zero-nearby" square is discovered (a process that makes clever use of recursive functions) is time-delayed to proceed in steps. A game over screen coincides with the creeper's explosion, along with an interval-based transparency fade. I really enjoyed adding these touches to the game, since they added up to create a polished experience.

In future versions, I'd like to add a difficulty selector, make use of animation methods to keep the block breaking animation fluid, and find a way to frontload assets so they do not take time to load upon the first playthrough (this is most noticeable on mobile). If you have feedback on how to make this better, I would love to hear it!


I've been an employee of KerfCase LLC since October of 2016. Working at a combination specialty wood shop and ecommerce company is a great way to pick up a lot of different skills, and during my time there I have learned a lot about small-batch production, online marketing, and how a small business functions.

KerfCase's website is built on the Shopify platform, which is a robust template-based ecommerce platform that allows for both WYSIWYG editing and direct code manipulation. Over the years, many developers and contractors have built on our theme, adding features and tweaking performance. Without having a developer on staff, we were locked into the basic look and functionality of the site, since a fundamental overhaul would be prohibitively expensive and labor intensive.

kerfcase collection page

As Kerf grew and began to diversify its product line, we reached a point where we wanted to change our branding to reflect our new identity. We hired a graphic designer to revise our logo and come up with a consistent visual and design language for our brand, including colors, typefaces, and layouts. The hope was that we would then hire a web developer on contract to apply these changes to our site.

kerfcase collection page

As luck would have it, I had begun studying programming, and felt confident that it would be great for my professional development, and much less expensive for the company, for me to take on the task of totally visually overhauling our site. Work began in May 2019 and the revamped design went live in July of 2019. Along the way I learned a lot about project planning, the software deployment process, and the quirks and tricks of managing a large production site.

Key features:

Mobile first

Mobile traffic forms the majority of our page views, so I began my design and style work focusing exclusively on mobile, coming around to desktop layouts late in the process. This helped me create consistent visuals and utility across the site, and made responsive design simple to implement.


Our graphic and user interface designers came up with a variety of grids and grid-based layouts to create a consistent and aesthetically pleasing interface. I had a lot of fun using photoshop and CSS to reproduce their mockups down to the pixel.

Menus and overlays

Creating dynamic menus and information-rich hover overlays gave our site a new dimension, and our users a quick way to get their bearings. I learned a lot about JavaScript and the DOM when implementing these features, but used pure CSS when possible.

kerfcase devices

It was evident from the start that if I wanted to be a web developer, the best way to do that would be to make a website.

Though there are lots and lots of tools and platforms for creating websites available now, none offer the total control that you get from putting your hands directly on the HTML and CSS of something you spun from whole cloth.

Not to mention the cost savings: Squarespace costs roughly as much as a Netflix subscription, whereas there are services that offer hosting for static sites absolutely free, and a domain name can be rented for pennies a month.

It turns out that making a good-looking, responsive, content-rich website in 2019 is a lot of work! Who'd have thunk it? But the process of starting with a blank text document and building up a portfolio piece-by-piece has been a deeply rewarding experience. is a mobile site with media queries for desktop users. I got the advice that mobile-first was a great way to tackle responsive design, and it did make it very easy to create a good-looking layout, then tweak individual elements for a beautiful desktop presentation.

So far JavaScript use is limited to the mobile "hamburger menu" and some form logic (if you ignore the game made entirely in JavaScript), but I want to do more with it as I improve the site. I'm a big fan of the way Apple uses JavaScript to fade-in or move screen elements as you scroll, and I want to learn more about that as I go.

I've focused on learning fundamentals, so no dependencies or frameworks are currently in use. If I decide to do a deep dive into Bootstrap or something similar, it might be a fun project to refactor the site. Maybe one day!

My minimum viable product for this page is that the copy is up and all the links work. I plan on tweaking it going forward to ensure that it's as content-rich as possible, and will be adding new blog posts regularly.

Hello, World!

I've written the "Your First Program" program a few times now, and in a few different languages. Whether you *include your stdio, or get right to the System.out.print()ing, it usually doesn't take long for a working program in a given language to be checked off your list. The hard part comes later, and can be very overwhelming.

I resisted majoring in Computer Science in college (and had more than one occasion to turn it down), and part of me has always wondered where I'd be if I had stuck with it. I've had a long and varied career, interacting with very smart and resourceful coworkers and using my technical knowhow and soft skills to teach tough concepts to unfamiliar minds. I have no regrets.

I have had, though, new responsibilities that exposed me to the world of code. A teammate left my company, and maintaining our large and ungainly website became my problem. At first, I knew just enough HTML and if/else logic to keep the shoestring and duct tape operation functioning normally, but I began wishing I had the tools and knowhow to improve the backend and make it run more smoothly and predictably.

In my spare time I started to teach myself computer science, coding, and software development, through a combination of books, online videos, and self-directed projects. What I have been thrilled to discover, after just 6 weeks of study, is that I really enjoy programming, and that many of the skills required for good code - delegation of tasks, focus in a distraction-prone environment, and attacking a problem from multiple angles (to name a few) - are skills that I've been actively honing for 10 years.

In years past I've sometimes fantasized about going back to school and getting a CS degree. A simple truth has been revealed to me recently that has energized my thinking: I don't have to do that. The cornucopia of resources available, for free, to anyone with determination and discipline are enough to fully master a valuable skill and open up one's horizons, without the 6 figures of debt.

I started this site to chronicle my journey into code, show off my projects, and maybe one day help others to take the leap and learn what you can do if you open up your terminal and start typing.

Hello, world!