projects

Curse of Strahd Obsidian Notes

I DM’ed my first D&D 5e campaign, and I might have picked the most complicated one for my first time 🙃. The Curse of Strahd campaign has a lot of information to keep track of, with a lot of complex relationships between NPCs and locations. In order to keep everything well organized, I decided to keep notes in Obsidian. Now that the party has completed over 25 sessions, I decided I had enough content to share with other DMs.

While the notes are pretty specific to our campaign and probably can’t be used as-is by other DMs, others may find the structure of the Obsidian vault helpful. Each character and location has notes and links to other related campaign entities. New DMs can copy this vault and update the notes to fit their own needs.

Accompanying the notes, I created an exact copy in the form of a website. I also created a spoiler-free zone on the site that has all of the session notes with links removed. There’s a spoiler-free handout section that has a list of all the items/maps the PCs have come across so far in the campaign. The handouts are marked as public or not using properties in their frontmatter.

Cultivator A Mobile Companion for Tiller

I really love the power that Tiller gives you. If you’re a spreadsheet nerd like me, it’s so nice to be able to do whatever you can imagine with your transaction data.

The problem with Tiller, however, is their lack of a mobile application. My wife and I have a few automated categorization rules set up for the most common reoccurring transactions, but the majority of our spending can’t be categorized automatically. Once every couple weeks, we used to have to gather around the PC, open the spreadsheet, and go through transactions line by line to manually assign categories to our spending. What we really wanted was a way to check in on our spending individually and on the go.

That’s why I built Cultivator. There are so many moments of down time in our lives that we can now use to quickly add a category or a note to our transactions. Then, when we finally gather around the PC to look at our budget, we don’t have to spend so much time trudging through transactions, but can focus on more important topics.

Cultivator is written in Angular and is a PWA so that it can be installed locally on your phone. The best part, however, is that it doesn’t require a bespoke backend. All the work happens between your browser and Google. When you first open the app, you’re prompted to authorize with Google to allow Cultivator to see your Tiller spreadsheet. Once you’ve granted permission and select your spreadsheet, the app automatically pulls in all your transactions and categories. From there, you can filter transactions down to only the ones that have not yet been categorized, and quickly click through them to add categories or notes.

All of this is happening locally! The browser requests the data directly from Google Sheets and writes the updates directly back to Google Sheets. I think this concept of BYOD (bring your own database) could prove really powerful for other applications as well. There’s no concern for scaling since each user is mapped to exactly one database (i.e. spreadsheet), privacy is strong since we’re not processing any user data outside of the browser, and costs are low since hosting static web files is cheap.

If you don’t use Tiller, I strongly suggest you check it out! And if you do already use it, try out Cultivator. It’ll make your budgeting go much more smoothly.


Auto Guest Login A Home Assistant Add-On

This is a Home Assistant Add-On that allows guests in your home to get logged into a guest account by visiting a url (maybe by simply scanning a QR code).

I originally created this project as a stand-alone node server that could be run on a Raspberry Pi in your house, then shared the idea as a blog post: The Completely Frictionless Way to Let Guests Use Home Assistant Don’t make guests download the home assistant app and use log in with guest credentials. Let this Add-On do all the hard work and just share a QR code. . But as the guest-login server started getting picked up by other Home Assistant users, I turned it into an Add-On that can be added to your Home Assistant host machine with just a couple button clicks.

Now it’s just as easy for those running a Home Assistant instance to get up and running as it is for their guests. Actually, if you use Home Assistant, you can get started by just clicking this button:

Open your Home Assistant instance and show the add add-on repository dialog with a specific repository URL pre-filled.


Halloween Candy Machine A hardware project

I created a machine to dispense Halloween candy to trick-or-treaters. When you walk up to the machine, you’re presented with a spinner on screen and a big, red, glowing, physical button to spin the wheel. Then, given a random distribution based on the amount of candy and the expected number of trick-or-treaters, you will receive prizes of varying sizes from a single mini snickers to a full-sized candy bar.

The entire system is run on a Raspberry PI 4. The software is written in python and uses the pygame library to operate the spinner on screen. After the user presses the button and the prize is selected, and array of stepper motors spin fans mounted in front of PVC pipes to dispense the prize.

Click below to see a video of the machine in action, or to read more about how it works.

Svordle Wordle Clone Written in Svelte

My wife and I got kind of addicted to playing Wordle. So much so, that playing once a day wasn’t quite scratching our itch. So I decided to make a clone of the game that could be played multiple times in a row.

For the last couple years before making this, I’d been hearing a lot about Svelte. Everyone who’d used it had told me it’s one of the best Javascript frameworks they’d worked with, so it seemed like this was the best time to give it a shot.

After putting this game together, I have to say I agree. The Svelte devs have done a fantastic job getting rid of the need for any boilerplate code. I was able to hop right in and create some of the smallest, easiest-to-understand components I’ve ever made in my career. I really hope to get to use it a lot more in the future.

Easy Wedding Jekyll Theme

Are you or a friend getting married? Do you want a quick way to make a customizable website? This is the theme for you!

When I got married, I created a website to commemorate the occasion as well as to provide information to my guests. Then not long after, I had a bunch of friends get married, who also wanted a site. I made the same site three times until I finally realized my life would be a lot easier if I could just use the same structure, but with different content. Enter Jekyll Theme: Easy Wedding.

It’s really easy to get started. The github README explains how to install and use the theme, then once you’ve done that, all that’s left is to change the data in a handful of yaml files. The best part is that if you set the theme as a dependency in a Gem file, you’ll get free updates as the theme improves.

Wedding Website

My wife, Sarah, and I got married June 15, 2019. to prepare for the occasion, I created a website to provide our guests with info about us and about the ceremony. To start, I forked wedding-website on github, then added some new content and features to make the site unique to us.

On the site, our guests were able to learn about how Sarah and I met, get to know the people in our wedding party, get directions or order an uber to the venue, find links to our gift registries, or get answers to common questions about the ceremony.

The coolest thing about the site, however, was that our guests could RSVP without filling out those so-easy-to-lose RSVP cards. The backend setup for the RSVP feature was super simple. The web app made requests directly to Google Sheets, so our guest list was automatically updated and easy to sort and search. Not only that, but Google Sheets allowed us to register event handlers to send our guests confirmation emails as well as notify Sarah and me that we’d gotten a new hit.

The wedding is already over, but you can still RSVP at the link below! (use code 0615)

Five in the Hive Fantasy Sports Web App

My roommate, Kane loves football! For years, he and his friends have played a fantasy football game with a bit of a twist. Each week during the season, each person chooses five NFL teams that they think will win against the Vegas spread for a specific game. In the past, everyone shared their picks in a group message, and calculated a leaderboard at the end of each week and again at the end of the season, but all that was a ton of work, so we made it easier!

Five in the Hive is Kane’s game as a web app. The app is hosted completely on AWS. The front-end is in Angular, hosted in S3, and distributed with CloudFront. The API is written in node, and hosted as a Lambda Function. The data-updating scripts are also hosted with Lambda but written in C#. We use DynamoDB as the database.

Click below to play! It’s a PWA, so if you love it, you can install it to your phone.

Squirrel Petting Simulator Computer Graphics Project

Squirrel Petting Simulator is a game I created for my computer graphics class. The shaders were required for the project, and were written using WebGL. The animation and the game mechanics I coded in just for fun. All of the 3D objects I borrowed from creators online.

Click below to play the game! The controls require a keyboard and mouse, and the game works best on Chrome.

Random Restaurant Amazon Alexa Skill

Random Restaurant is an Alexa Skill that helps people decide where to eat. Often, friends may disagree on what to have for dinner, or if someone is new to an area, they may not be aware of all the nearby food options. Users can simply say “Alexa, ask Random Restaurant for a place to eat”, and the app will give them a restaurant recommendation that is nearby and currently open.

The Skill is hosted on AWS as a node.js lambda function. It works by collecting the user’s address from the device that makes the request. It then passes that information to the Yelp public API, which returns a list of nearby and open restaurants. From that list, one restaurant is randomly chosen and suggested to the user. Users can also request a specific type of food or limit the price range of the suggested restaurant.