Success metrics

Arguably the single most important part of any project that everyone skips is defining what makes a project successful.

The Traps to Avoid

Doing so focuses the project and, more importantly, will help you ignore three big traps:

  • Taking on other people’s definitions of success.
  • Never finishing.
  • Grabbing onto tantalizing data that don’t actually support your goals.

Other People’s Ideas of Success

Often–always, actually-–when working on a project people will offer opinions and ideas on what you should do with it. This is human nature and is a lovely thing. If you’re not sure in what you want though, well, it’s easy to take on their thoughts as your own. Feedback is good, taking it all in means that you’re not secure in why you’re doing what you’re doing.

A lot of what people will suggest means success is going to have to do with capitalism. Always remember that you are not required to monetize your joy.

Never Finishing

Finishing anything is hard. It’s so hard.

The last 10% of even the best scoped projects is always 1000% of the work. Nothing will kill your momentum during that difficult phase more than not knowing what you’re actually shooting for.

You get lost, flail about for a bit, and put it down forever. It’ll make you feel guilty for a long time too whenever you think about it.

Tantalizing Data

Social Media figured out years ago that people like having numbers attached to their posts. Engagement metrics are, frankly, super fun because it’s a nice dopamine hit to see strangers interact with your posts! My guess is that with any interrogation though you’ll find that your reasons for posting are not to see analytics numbers tick up.

You’re probably, at a minimum, more interested in a specific audience liking and retweeting your work. Or, the actual reason you’re posting on social media might be to sell your project, generate commissions, share it with a group, keep a diary for yourself, OR any number of totally valid reasons to use social media.

A large number of favs, shares, and/or retweets is rarely going to be your project’s actual goal. If it is, you can go and buy those likes and retweets from many numerous shady websites with a minimum amount of fuss.

A Personal Example

To personalize this: the primary goal of the posts on this blog are to help me organize my thoughts and to reference them later on. A secondary goal is to share posts with my social circles. A tertiary goal is for random folks on the internet to find the posts when they’re looking for specific information.

This post was written as a reminder to myself to avoid mistakes I’ve made in the past. I’ve walked directly into all of the three traps above and will likely continue to do so. If anyone else reads this post hopefully they’ll be able to use it as ammunition against me the next time I dive in headfirst into a project without a goal.

If my primary goal was to achieve some sort of Elite Blogger Status I’d have to do things a lot differently. Probably there would be no cryptic posts about goal setting! Not going after that particular goal frees me up do what I actually want with this little corner of the internet and not obsess too much over analytics numbers.

From Hugo to WordPress

There are a million and one blog posts for “move from WordPress to Hugo!” out there. This is the opposite of that.

Hugo is good

I like Hugo a lot. If you need a static site generator I’d recommend it without reservation! Once I had it going it worked very well. I loved how fast Hugo could build the entire site and it required almost no server resources. Turns out, you don’t need that much raw computing power to serving static files to a handful of folks every day.

Posting though

But…posting was far more complex than I wanted it to be. In the end I was syncing a folder via dropbox, committing my code to a repo, pushing it to a repo on the server. From there a git hook would run to build the site and then move the files to a folder. Extremely cool and extremely obtuse. If I had just one computer it wouldn’t have been that big of a deal to continue on; however, because I’m a glutton for complication, I bounce between 5 different devices (3 macs, 2 iOS devices) within the course of a week.

Having a web interface to log into matches my mental model of “I am writing and publishing” much better. I also dearly appreciate having drag and drop image support as well as WYSIWYG formatting options. Hugo’s support for non-text media is lacking. That’s totally okay! But, I was finding that I was avoiding publishing certain kinds of posts because I was lacking easy tools to do so.

WordPress and Gutenberg

What finally pushed me to make this change was a recent experience building a new website for Workantile. During that redesign we relied on the Gutenberg editor for formatting our pages. I was impressed! You can create fairly complex pages quickly with blocks in a way that just wasn’t easily doable a few years ago without diving deep into theme files. We’re in a bit of a rough transition point going from the classic editor to Gutenberg (and more importantly the concept of Blocks). It’s getting better all the time though!


The move went pretty well for the most part. Some technical issues I ran into:

RSS Importer

The RSS importer that is built into wordpress needs some serious attention. The biggest issue is that it fails because it’s calling a deprecated PHP function. The fix for this for me was to comment out the offending line. This StackOverflow post was helpful:

php – Call to undefined function set_magic_quotes_runtime() – Stack Overflow

I just found line 72 in the importer and commented it out. I wouldn’t rely on this edit for an import where you didn’t control all of the content, or as an importer you run more than once. It’s a brittle fix to say the least. Here’s the error and stack trace:

An error of type E_ERROR was caused in line 72 of the file /var/www/ Error message: Uncaught Error: Call to undefined function set_magic_quotes_runtime() in /var/www/
Stack trace:
#0 /var/www/ RSS_Import->get_posts()
#1 /var/www/ RSS_Import->import()
#2 /var/www/ RSS_Import->dispatch()
#3 {main}

Hugo’s RSS Implementation

And on the Hugo end of things: Hugo’s built-in RSS generator doesn’t include the full text of the posts. It also doesn’t include categories. I happen to be the sort of person who likes adding categories, so this was a problem! Here’s a gist of my RSS theme file that has the full text and categories:

Hugo RSS Implementation with Categories · GitHub

This looks for the categories set in the frontmatter of your markdown files. If there are none it skips it and nothing is added to the feed for that post.

RSS Redirect

I wanted to make sure anyone who subscribed to my old RSS feed continues to get the new one. To do so I set up a 301 redirect using this plugin:

Simple 301 Redirect

Keeping it around since it’s always nice to have this in a readily accessible place.


Moving images over to the new site involved making sure they were uploaded appropriately to WordPress’ Media library. I toyed with the idea of doing one big import and going through and fixing individual images. Then I found this plugin that just did it for me. Installed it and then Edited all of my posts and resaved them. It ran through and copied everything over and updated the src tags for me:

Auto Upload Images – WordPress plugin |

Inserting images in Hugo was one of the reasons I wanted to get away from it so this was nice to have it just work. After I ran this I turned it off.


So far, so good. I’m happy with this and this post was fully written and edited in the WordPress editor. It’s nice to have “my website” compartmentalized to something I go to on the internet to edit, although I will miss how much posting a blog post made me look like I was attempting to hack the planet.

Newsletter April 9, 2018

Here are the Other Local Newsletters You Should be Reading

Reader and RSS

Anil Dash tweeted a sentiment that resonated a lot with me:

Google’s decision to kill Google Reader was a turning point in enabling media to be manipulated by misinformation campaigns. The difference between individuals choosing the feeds they read & companies doing it for you affects all other forms of media.

I used to be a multiple-times-daily checker of my RSS feeds. I’d read a bunch, follow threads, add more feeds, and repeat. Then twitter came along. I joined because my friend Keller was into it and it became just one part of Being Extremely Online.

The Timeline slowly started sucking my attention away from RSS. Then Reader went away, but it was okay, most of my feeds were still in twitter, or people were sharing the important stuff. Then, well, then twitter and facebook started becoming just completely outsized and I am adrift.

They are less like a curated timeline and more like a vicious surprise machine. That machine used to be set on “compelling links and ideas” and is now cranked to “emotional whiplash, you coward”. Someone broke the level off too.

Anil also wrote a piece about The Missing Building Blocks of the Web that, goodness, is good. Whatever it is I’m saying poorly, Anil has said much better.

Twitter and APIs

Speaking of Twitter. It’s still marginally useful through the use of a 3rd party app–I use Tweetbot. That might go away soon though.

Moves like this are exactly why we all need our own spaces. In the beginning Twitter was extremely permissive of developers using its API. They’ve slowly been cutting features from that and this next moves sounds like it might spell the end for most of the mainstay apps.

The Angry Motorcylce Men Meme

It’s my favorite meme at the moment

This is Just to Say.


And this is a fantastic cap to whatever it is current meme culture is at right now.

This is absolutely going to be unparseable in a few years. Right now it’s very good.

Macbooks should have touchscreens

Turning a MacBook into a Touchscreen with $1 of Hardware.

I used to think touchscreens on laptops was a bad idea until I observed that, no, people actually do use them. Apple has held the line that this is a bad user interface. I think they’re wrong about it. I mean, they sell a keyboard attachment for the ipad that also doesn’t turn off the touch functionality of the ipad…clearly there’s some disagreement within the company.

If you’ve seen a normal non-coder someone operate a computer with a touchscreen you’ll see them use it. Touching the screen is such a great affordance that we all carry devices around in our pockets that are purpose built to do such a thing. My toddler is confused when you can’t touch the screen and make it do something.

Toddler QA

Speaking of toddlers, if you ever want to find interface bugs hand your app to a toddler.

We released the 1.1 bug fix update to Night Lights last week and then promptly found that the main issue we were trying to fix (sometimes you get the same color, shape, or BOTH) was still happening. After a lot of fiddling we figured out that our toddlers were executing a frame perfect trick to reshuffle the available colors in the middle of them changing. Good job toddlers!

1.2 fixes that bug and the other one we introduced where the light bulb wouldn’t light up. Trust me, there is no such thing as a simple app.

Codename Hyper Hunter

Kyle made a bunch of concept pixel art for a game we’re Codenaming Hyper Hunter. The pitch for it is that it’s a cross between Mega Man and Mario. You can both shoot and jump on enemy’s heads. As part of our discussion on what the game should be we’ve been replaying various NES Mega Man’s and taking notes. What’s most interesting about that exercise is that most of the difficulty in Mega Man is environmental platforming (tricky jumps, modified friction/physics, different combinations of simple enemies) until you hit the Robot Master in each level. Then it’s mostly what you remember: combat and weapon choices.

If you have a favorite Mega Man level please let me know. We’re planning more deep dive level dissections and I’d love to take a look at particularly interesting ones.

You Should Blog

This is my invitation for you to start blogging. Start it up again, or start it for the first time. Over a year ago I started blogging again. Nothing major, just small things here and there mostly for my own reference. It’s a good habit and it’s freeing to have a place to put things. I talked last week about ownership on the web and have gotten a lot of nudges from folks that this is something. I’m now nudging you to actually do it because I know you’ve been thinking about it. Talk to me if you need help getting setup, or need accountability. I’m very good at positive peer pressure.

Being Happy For Your Friends

Friends, I want to share one of the most important things I learned in grad school: other people’s success is not your failure. You’ll be so much happier if you learn to celebrate the achievements of other people as well as your own.

A while back on Workantile’s slack we created channel for #shamelessplugs. Its a channel devoted to talking about the cool things you are up to. This has been lovely and provides a valuable service to a community: giving people the space to be excited about their thing. If you’re on slack or discord or whatever and don’t have a channel like this, go make one.

Jekyll to Hugo Along with an Updated Deployment Script

I moved my blog from Jekyll to Hugo because I can’t leave well enough alone.

Jekyll is wonderful, it’s also slower than it should be for building a site. Not like “go get some coffee” slow, but building felt sluggish. I also needed to reconfigure my workflow for publishing anyway. My earlier workflow involved running Jekyll client-side, keeping the resulting _site folder in version control and deploying that.

Trust me, it made a lot of sense when I was setting it up. However, it quickly started to show its fragility.

My primary goal was to have the server generate the site itself so I needed to start from scratch anyway. This seemed like a good opportunity to try Hugo. I also wasn’t running ruby on my webserver yet and, frankly, installing Hugo was a lot easier than the full ruby setup:

sudo apt install hugo

And that was about it for setup on the server.

Hugo and Jekyll both use markdown files to generate the site and their frontmatters are similar enough that the transition to Hugo was incredibly simple.

Fast forward through a lot of futzing with config files, themes, and testing builds.

I eventually landed on this: I keep the project in version control and .gitignore the exported site from the repo. The site can still be built locally if needed with hugo serve but when the project is commited it ignores the exported site. After the commit is pushed to the server it runs the following post-recieve hook:

#Checkout the repo to a temporary build folder
git --work-tree=/var/repos/hugoblog/tmpbuild/ --git-dir=/var/repos/hugoblog/ checkout -f
#Build the site
hugo -s /var/repos/hugoblog/tmpbuild/
echo "\n\nBlog has been built. Moving it to\n\n"
#Then move the public folder to the right place
rsync -r /var/repos/hugoblog/tmpbuild/public/ /var/www/

Nothing terribly fancy and this will likely get modified into the future. It checkouts the project to a folder, runs Hugo, tells me it worked, then moves it over with rsync.


I did run into a theme issue with git that stumped me for a bit. The theme was cloned in using git. Since it had its own git repo it wasn’t getting tracked by the project’s git repo. After pushing it to the server hugo was generating a blank site since the theme was blank.

My fix was to copy/paste the theme into a differently named folder, update config.toml to that theme folder, and then add another commit. After that it worked. I’m sure this is the sort of thing that could be solved leveraging git in some way I don’t quite understand, but this was easier for me. I also anticipate designing my own theme.