blog

Half-assing it with everything you've got


🔗 a linked post to lesswrong.com » — originally shared here on

If you're trying to pass the class, then pass it with minimum effort. Anything else is wasted motion.

If you're trying to ace the class, then ace it with minimum effort. Anything else is wasted motion.

If you're trying to learn the material to the fullest, then mine the assignment for all its knowledge, and don't fret about your grade. Anything else is wasted motion.

If you're trying to do achieve some combination of good grades (for signalling purposes), respect (for social reasons), and knowledge (for various effects), then pinpoint the minimum quality target that gets a good grade, impresses the teacher, and allows you to learn the material, and hit that as efficiently as you can. Anything more is wasted motion.

Ah, an engineer’s approach to optimizing life.

There is a good section in here as well about how to deal with the associated guilt when you take this approach.

Continue to the full article


Blazing Trails with Rails, Strava, and ChatGPT

originally shared here on

a cute animated bicycle using a laptop that has a helmet on it

The main page of my personal website features a couple of lists of data that are important or interesting to me.

The "recent posts" section shows my five most recent blog entries. Rails makes that list easy to cobble together.

The "recent listens" section shows my five most recent songs that were streamed to Last.fm. This was a little more complex to add, but after a couple of hours of back and forth with ChatGPT, I was able to put together a pretty hacky solution that looks like this:

  1. Check to see if your browser checked in with last.fm within the last 30 seconds. a. If so, just show the same thing I showed you less than 30 seconds ago.
  2. Make a call to my server to check the recent last.fm plays.
  3. My server reaches out to last.fm, grabs my most recent tracks, and returns the results.

Pretty straight forward integration. I could probably do some more work to make sure I'm not spamming their API[^1], but otherwise, it was a feature that took a trivial amount of time to build and helps make my website feel a little more personal.

Meanwhile, I've been ramping up my time on my bike. I'm hoping to do something like Ragbrai or a century ride next year, so I'm trying to building as much base as I can at the moment.

Every one of my workouts gets sent up to Strava, so that got me thinking: wouldn't it be cool to see my most recent workouts on my main page?

How the heck do I get this data into my app?

Look, I've got a confession to make: I hate reading API documentation.

I've consumed hundreds of APIs over the years, and the documentation varies widely from "so robust that it makes my mind bleed" to "so desolate that it makes my mind bleed".

Strava's API struck me as closer to the former. As I was planning my strategy for using it, I actually read about a page and a half before I just said "ah, nuts to this."

A Frinkiac-generated image repurposing a Smithers quote where he says "Aw, nuts to this, I'll just get Homer Simpson", but gsub Homer Simpson for ChatGPT.

Knowing my prejudice against reading documentation, this seemed like the perfect sort of feature to build hand-in-hand with a large language model. I can clearly define my output and I can ensure that the API was built before GPT-4's training data cutoff of September 2021, meaning ChatGPT is at least aware of this API even if some parts of it have changed since then.

So how did I go about doing this?

A brief but necessary interlude

In order to explain why my first attempt at this integration was a failure, I need to explain this other thing I built for myself.

I've been tracking every beer I've consumed since 2012 in an app called Untappd.

Untappd has an API[^2] which allows you to see the details about each checkin. I take those checkins and save them in a local database. With that, I was able to build a Timehop-esque interface that shows the beers I've had on this day in history.

A sample of my This Day in Untappd History dashboard

I have a scheduled job that hits the Untappd API a handful of times per day to check for new entries.[^3] If it finds any new checkins, I save the associated metadata to my local database.

Now, all of the code that powers this clunky job is embarrassing. It's probably riddled with security vulnerabilities, and it's inelegant to the point that it is something I'd never want to show the world. But hey, it works, and it brings me a great deal of joy every morning that I check it.

As I started approaching my Strava integration, I did the same thing I do every time I start a new software project: vow to be less lazy and build a neatly-architected, well-considered feature.

Attempt number one: get lazy and give up.

My first attempt at doing this happened about a month ago. I went to Strava's developer page, read through the documents, saw the trigger word OAuth, and quickly noped my way out of there.

...

It's not like I've never consumed an API which requires authenticating with OAuth before. Actually, I think it's pretty nifty that we've got this protocol that allows us to pass back and forth tokens rather than plaintext passwords.

But as a lazy person who is writing a hacky little thing to show my workouts, I didn't want to go through all the effort to write a token refresh method for this seemingly trivial thing.

I decided to give up and shelve the project for a while.

Attempt number two: Thanks, ChatGPT.

After a couple of weeks of doing much more productive things like polishing up my upcoming TEDx talk, I decided I needed a little change of context, so I picked this project back up.

Knowing that ChatGPT has my back, I decided to write a prompt to get things going. It went something like this:

You are an expert Ruby on Rails developer with extensive knowledge on interacting with Strava's API. I am working within a Rails 5.2 app. I would like to create a scheduled job which periodically grabs any new activities for a specific user and saves some of the activity's metadata to a local database. Your task is to help me create a development plan which fulfills the stated goal. Do not write any code at this time. Please ask any clarifying questions before proceeding.

I've found this style of prompt yields the best results when working on a feature like this one. Let me break it down line by line:

You are an expert Ruby on Rails developer with extensive knowledge on interacting with Strava's API.

Here, I'm setting the initial context for the GPT model. I like to think of interacting with ChatGPT like I'm able to summon the exact perfect human in the world that could solve the problem I'm facing. In this case, an expert Ruby on Rails developer who has actually worked with the Strava API should be able to knock out my problem in no time.

I am working within a Rails 5.2 app.

Yeah, I know... I really should upgrade the Rails app that powers this site. A different problem for a different blog post.

Telling ChatGPT to hone its answers down on the specific framework will provide me with a better answer.

I would like to create a scheduled job which periodically grabs any new activities for a specific user and saves some of the activity's metadata to a local database.

Here, I'm describing what should result after a successful back and forth. A senior Rails developer would know what job means in this context, but if you aren't familiar with Rails, a job is a function that can get scheduled to run on a background process.

All I should need to do is say, "go run this job", and then everything needed to reach out to Strava for new activities and save them to the database is encapsulated entirely in that job.

I can then take that job and run it on whatever schedule I'd like!

Your task is to help me create a development plan which fulfills the stated goal.

Here, I'm telling ChatGPT that I don't want it to write code. I want it to think through[^4] and clearly reason out a development plan that will get to me to the final result.

Do not write any code at this time.

The most effective way I've used ChatGPT is to first ask it to start high level (give me the project plan), then dig into lower levels as needed (generate code). I don't want it to waste its reasoning power on code at this time; I'd rather finesse the project plan first.

Please ask any clarifying questions before proceeding.

I toss this in after most of my prompts because I've found that ChatGPT often asks me some reasonable questions that challenge my assumptions.

Now, after a nice back and forth with ChatGPT, I was able to start down a path that was similar to my Untappd polling script.

As I was approaching the point where I could first test my example, I went to go read the documentation and came across an entire section that discussed webhooks.

[cue record scratch]

Wait up... webhooks?!

A sojourn into webhooks

If you've made it this far into the article, I'm assuming you're a little bit technical, but in the interest of not making assumptions, I'll briefly explain the concept of webhooks.

If you look at how I'm integrating with the Untappd API, you can see I'm periodically reaching out to their API to see if there's any new checkin activity. This method is called polling.

Webhooks are kind of the opposite: when I complete an activity within Strava, Strava can reach out to my app and say, "there's a new activity for you." Once I get that notification, I can reach out to their API to fetch the new activity details.

For my Strava app, this is a much better[^5] way of doing things. I no longer need to poll for new information; I can just wait for Strava to tell me when action needs to be taken.

But, of course, when I first told ChatGPT to help me with this solution, it didn't mention webhooks. And why would it? I never told it "give me the best solution for this problem." I said "here's my problem and a proposed solution, go ahead and give me the path forward."

I'm a bit frustrated that I didn't see the webhook option initially. I'm even more frustrated that ChatGPT only mentioned it well after we started down this path, and only after I asked it point blank:

Does Strava offer a web hook API?

Yes, Strava does offer a webhook API. Webhooks allow you to receive real-time updates about athlete activities, which can be more efficient than periodically polling for new data. Here's a brief overview of how to set up and use Strava webhooks:

[brief outline complete with things to consider with this approach]

Attempt number three: finally.

While considering my original prompt, I gave it this new one:

Okay, I'd like to incorporate webhooks into this workflow. Here's what I'd like to have happen:

1. Let's add the infrastructure in place to subscribe to webhook notifications within my Rails 5.2 app.
2. When a webhook is sent to my server, I'd like to either:
    a. make a call to Strava's API to fetch that activity's information and save that information in my local database, or;
    b. use the updates field to update the locally saved information to reflect the changes

Knowing this simple walkthrough, first create me a detailed development plan for setting my app to be able to fully handle webhook notifications from Strava.

What resulted here was a detailed walkthrough of how to get webhooks incorporated into my original dev plan.

As I walked through the plan, I asked ChatGPT to go into more detail, providing code snippets to fulfill each step.

There were a few bumps in the road, to be sure. ChatGPT was happy to suggest code to reach out to the Strava API, but it had me place it within the job instead of the model. If I later want to reuse the "fetch activities" call in some other part of my app, or I want to incorporate a different API call, it makes sense to have that all sitting in one abstracted part of my app.

But eventually, after an hour or so of debugging, I ended up with this:

The final result: a list of my 5 most recent activities on Strava.

Lessons learned

I would never consider myself to be an A+ developer or a ninja rock star on the keyboard. I see software as a means to an end: code exists solely so I can have computers do stuff for me.

If I'm being honest, if ChatGPT didn't write most of the code for this feature, I probably wouldn't have built it at all.

At the end of the day, once I was able to clearly articulate what I wanted, ChatGPT was able to deliver it.

I don't think most of my takeaways are all that interesting:

  • I needed to ask ChatGPT to make fixes to parts of code that I knew just wouldn't work (or I'd just begrudgingly fix them myself).
  • Occasionally, ChatGPT would lose its context and I'd have to remind it who it was[^6] and what its task is.
  • I would not trust ChatGPT to write a whole app unsupervised.

If I were a developer who only took orders from someone else and wrote code without having the big picture in mind, I'd be terrified of this technology.

But I just don't see LLMs like ChatGPT ever fully replacing human software engineers.

If I were a non-technical person who wanted to bust out a proof of concept, or was otherwise unbothered by slightly buggy software that doesn't fully do what I want it to do, then this tech is good as-is.

I mean, we already have no-code and low-code solutions out there that serve a similar purpose, and I'm not here to demean or denigrate those; they can be the ideal solution to prove out a concept and even outright solve a business need.

But the thing I keep noticing when using LLMs is that they're only ever good at spitting out the past. They're just inferring patterns against things that have already existed. They rarely generate something truly novel.

The thing they spit out serves as a stepping stone to the novel idea.

Maybe that's the thing that distinguishes us from our technology and tools. After all, everything is a remix, but humans are just so much better at making things that appeal to other humans.

Computers and AI and technology still serve an incredibly important purpose, though. I am so grateful that this technology exists. As I was writing this blog post, OpenAI suffered a major outage, and I found myself feeling a bit stranded. We've only had ChatGPT for, like, 9 months now, but it already is an indispensable part of my workflow.

If you aren't embracing this technology in your life yet, I encourage you to watch some YouTube videos and figure out the best way to do so.

It's like having an overconfident child that actually knows everything about everything that happened prior to Sept. 2021 as an assistant. You won't be able to just say "take my car and swing over to the liquor store for me", but when you figure out that sweet spot of tasks it can accomplish, your output will be so much more fruitful.

I'm really happy with how this turned out. It's already causing me to build a healthy biking habit, and I think it helps reveals an interesting side of myself to those who are visiting my site.

[^1]: Maybe I can cache the data locally like I'm doing for Untappd? I dunno, probably not worth the effort. 😅 [^2]: Their documentation is a little confusing to me and sits closer to the "desolate" end of the spectrum because I'm not able to make requests that I would assume I can make, but hey, I'm just grateful they have one and still keep it operational! [^3]: If we wanna get specific, I ping the Untappd API at the following times every day: 12:03p, 1:04p, 2:12p, 3:06p, 4:03p, 5:03p, 6:02p, 7:01p, 8:02p, 9:03p, 10:04p, and 12:01a. I chose these times because (a) I wanted to be a good API consumer and not ping it more than once an hour, (b) I didn't want to do it at the top of every hour, (c) I don't typically drink beers before 11am or after 11pm, (d) if I didn't check it hourly during my standard drinking time, then during the times I attend a beer festival, I found I was missing some of the checkins because the API only returns 10 beers at a time and I got lazy and didn't build in some sort of recursive check for previous beers. [^4]: Please don't get it twisted; LLMs do not actually think. But they can reason. I've found that if you make an LLM explain itself before it attempts a complex task like this, it is much more likely to be successful. [^5]: Baga Chipz saying "much better" on an episode of RuPaul's Drag Race [^6]: Mufasa telling Simba to remember who he is in the Lion King


The Mystery of the Bloomfield Bridge


🔗 a linked post to tylervigen.com » — originally shared here on

Why is this bridge here?

This pedestrian bridge crosses I-494 just west of the Minneapolis Airport. It connects Bloomington to Richfield. I drive under it often and I wondered: why is it there? It's not in an area that is particularly walkable, and it doesn't connect any establishments that obviously need to be connected. So why was it built?

I often have curious thoughts like this, but I dismiss most of them because if I answered all of them I would get nothing else done. But one day I was walking out of a Taco Bell and found myself at the base of the bridge.

That only raised MORE questions! Why did the bridge just lead to some grass? Why isn't there a sidewalk? What is the point? It makes no sense!

Those who grew up in the Richfield/Bloomington area in the same era as me must have driven under this bridge thousands of times, and I, myself, have certainly had this thought.

The answer to the question is straight forward, but I will not spoil it for you.

Instead, I urge you to read this entire post, top to bottom, because this post is a journey, not a destination. The author spends months trying to get to the bottom of why this mysterious bridge was erected, and the whole article is masterfully written.

Continue to the full article


The Riddle of Rest


🔗 a linked post to moretothat.com » — originally shared here on

The reason why a still lake is the archetype for a still mind is because it flows without any intention. The currents softly rise without breaking, and in the instances where it does, it happens without aggression. There’s nothing it’s trying to do; it’s simply going where it needs to go.

But drop a stone into the lake, and the ripples flow out in a way that goes against the state of nature. Even a harsh gust of wind won’t create ripples in the way that a small stone does. That’s what it means to desire more than what you have; to become somebody or to further your place in a community. Your presence may be known, but it may do so at the expense of the stillness around you.

Rest is to take those moments to understand that you’re not defined by what you produce, and to be okay with whatever you are. It’s to allow that emptiness of mind to prolong whenever you see something beautiful, and to understand that this is not an anomaly, but a glimpse into the reality of what truly is.

Continue to the full article


Politics, Friendship, and the Search for Meaning


🔗 a linked post to comment.org » — originally shared here on

Imagine, by analogy, a virtuoso pianist at the peak of her career who looks out at the culture around her and realizes that appreciation for classical music is rapidly fading. She senses a crisis: if things continue, there will soon be no audiences, no careers in music, and no future great performances. She considers the situation so dire that she decides to step away from her instrument, if only for a time, in order to defend classical music nationwide. She gives speeches about composers in grade schools across the country, lobbies Congress for increased support for the arts, and solicits wealthy donors to sponsor classical-music instruction. Her work is noble, but it consumes her; and the crisis is so severe that her task is never done. Thus, she never fully returns to the life of music she enjoyed before. Now, when she has time to play, which is rare, she’s a shadow of her former self. Practice sessions find her distracted. Her music suffers as a result of her effort to save music.

The battle to save music is not itself the practice of music. The two activities are worlds apart. One is an instrumental good, the other intrinsic; one is never complete, the other complete in itself. This paradox occurs across domains: The battle to preserve a space for Christian worship in an increasingly secular society is not itself Christian worship. The defence of the liberal arts is not the liberal arts. And the war to save our political union from our enemies is not itself political union.

A pretty heavy article that makes a few great points about nihilism, politics, friendships, and meaning.

My only quibble is that the article makes an unnecessary leap about not being able to be complete without a relationship with God, but hey, maybe the longer I live and partake in intrinsic activities, those experiences will help change my opinion about why we’re here and what set this world into motion.

Continue to the full article


Your brain does not process information and it is not a computer


🔗 a linked post to aeon.co » — originally shared here on

The information processing (IP) metaphor of human intelligence now dominates human thinking, both on the street and in the sciences. There is virtually no form of discourse about intelligent human behaviour that proceeds without employing this metaphor, just as no form of discourse about intelligent human behaviour could proceed in certain eras and cultures without reference to a spirit or deity. The validity of the IP metaphor in today’s world is generally assumed without question.

But the IP metaphor is, after all, just another metaphor – a story we tell to make sense of something we don’t actually understand. And like all the metaphors that preceded it, it will certainly be cast aside at some point – either replaced by another metaphor or, in the end, replaced by actual knowledge.

As someone who makes a living (in part) by deploying metaphors to explain complex ideas, it is both harrowing and inspiring to learn how flawed the “your brain is a computer” metaphor actually is.

Despite the despair, this essay does a great job explaining why it is no longer a useful metaphor, and leaves you with the curiosity needed to explore and find a new, more helpful metaphor (or, as the pull quote says, “actual knowledge”).

Continue to the full article


Why Faulty Streetlights Are Turning Cities Purple — and Why It's Worrisome


🔗 a linked post to businessinsider.com » — originally shared here on

People feel like something intimate, something definitional about their city, has been taken away. So they look for intention. Maybe it's for a holiday? Maybe it's a conspiracy? It has to mean something. Because if it doesn't, that's even scarier. Streetlights and street lighting are a city's deep infrastructure. If they can break in such a weird and unexpected way, so can everything else.

I’ve recently noticed some street lights in Apple Valley turning purple. I thought it looked intentional and kinda cool, to be honest, especially here in Prince/Vikings country.

But the part that I pull quoted is something on my mind a lot lately.

We all take tech for granted, yet the thing we appreciate least of all is how much we don’t know regarding how all this stuff comes to be.

It reminds me of the essay about how nobody actually knows how a pencil gets made. You’ve got separate manufacturers who know how to assemble the individual parts (erasers, lead, wood, etc.), but all of those folks rely on other sources for raw materials.

The further you go down, the more you realize civilization really does hinge on a bunch of trusting handshakes presumably done over Zoom these days. And that’s a sentiment that is equal parts romantic and terrifying.

Continue to the full article


How to Limit What You Say "Yes" To


🔗 a linked post to explorewhatworks.com » — originally shared here on

I’d like to offer a tool to put in your emergency kit for shifting self-sabotage to self-care and going from overcommitted to well-resourced. And that is managing for whole capacity—rather than simply time or money. In other words, don’t ask, “Can I squeeze this in?” when presented with an opportunity. Ask, “Do I have what I need to do this well?”

Continue to the full article


On Impostor Syndrome


🔗 a linked post to tiktok.com » — originally shared here on

I saw this TikTok from Chelsea Fagan shared on a Slack community I'm part of, and I thought it was worth transcribing the whole thing and leaving it here for future reference.

So one thing about me is that I never have impostor syndrome, and it's not because I automatically think I'm great at anything I try... it's more that I realized that basically every industry is full of idiots.

I genuinely think that a lot of people who haven't been in the corporate world or exposed to it too much don't realize just how many successful people are mediocre at best at what they do.

And it makes sense when you consider all the factors that are usually required for people to reach a high level at a given industry. Things like having connections, having enough generational wealth to go to college and get an advanced degree, nepotism, networking, and all of those other things. Not to mention all of the other white, cis, male privileges that often go into success.

But by the time you reach the highest levels of most industries, you're often working with people who can barely put together an email.

Or you'll be on an email thread with 17 different people, none of whom seem to actually have a job.

Half of the executives have administrative assistants who do the vast majority of their actual work.

And this is true of a lot of creative industries... think of how many famous people are out there who have almost no discernible talent.

A driving force in my life is looking at something and being like "I could absolutely do better than that", and then I give myself permission to do it.

And just being the kind of person who is conscientious enough about the work you're doing to even consider having impostor syndrome, or think about whether or not you're good enough to be doing it, you're probably already better than most of the people there.

Related: this quote from Sarah Hagi:

Lord, grant me the confidence of a mediocre white man.

Continue to the full article


The Number Ones: Crazy Town’s “Butterfly”


🔗 a linked post to stereogum.com » — originally shared here on

My last handful of posts were a bit depressing... so I thought I'd share this one that was in my Instapaper queue for some reason.

I love the idea that someone at Stereogum is reviewing every single number one hit since 1958, and it brings me a great deal of joy that they needed to write a piece about this song.

The summary nails it here:

As a band, Crazy Town were fucking godawful, and they were the kind of godawful that’s easy to mock. But “Butterfly”? I’ve never been mad at “Butterfly.” It’s the kind of silly bullshit hit song that makes the world just slightly more fun. Rap-rock faded away in the rearview a long time ago, but “Butterfly” will always evoke a very particular moment. That moment was short, just as it should’ve been. Butterflies aren’t built to live forever.

A recent revelation of mine is that I've kind of been a music snob for most of my life. I basically turned my nose up at the entire emo/punk genre sometime in middle school and never took the time to re-evaluate that position.

Now that I'm in my mid-thirties, I've been letting go of those unnecessary positions, and I probably don't need to be the one to tell you this, but there's a lot of good pop-punk and emo stuff out there.

I've also found myself lately drawn toward music that reminds me of my middle/high school years. Rap rock is a defining genre of that time for me, and Butterfly is one of those songs that will forever transport me to a time when I would load 5 incredibly compressed MP3s onto my 16MB (that's megabyte, not gigabyte) Cybiko MP3 player and bike up to the middle school for football practice.

Continue to the full article