A Sunday Afternoon Project

4 min read A Sunday Afternoon Project

Sam Altman said there are two kinds of startups:

  1. the ones that build for models as they are today, and
  2. the ones that build for models as they will be.

Obviously, the latter category is a better place to be in. The same applies to your little projects: they should be able to harness a linear increase in intelligence with time.


My job today is radically different from my previous jobs. It's part relationships, part management, part architecture, part problem solving, and part reviewing code. Mostly, it requires me to think ahead by a few steps of our engineers, the company as a whole, and our enemies. All of it is risk intelligence.

I try to focus on the most important things nobody else in the company can do. That means delegating the things that other people can do (esp. when they're better at that thing than I am). Writing code is one of those things.

To be clear, I couldn't do my job if I were not technical. In the sausage-making of a product, there are many branches, and choosing right means tradeoffs, and understanding risk.

Risk Intelligence
A friend wrote this book I read about ten years ago. I understood that I didn’t understand risk. I was a “word thinker”--someone who would rely on internal argumentation vs a visceral understanding of risk, especially tail risk. I vowed to be able to understand risk. And I paid

My team is better at coding than I am. So I don't get to do a lot of it. And sometimes I have to carve out the time to rediscover that beautiful, innocent joy of making. Even the little things.

One of my side projects has about a thousand users. They literally cost me money. Sometimes I forget they're there. I could charge, but I don't really want to nor do I have the time to. I just like having them. And I only really find out they're there when some API breaks and I have to fix it.

Sometimes I do side projects. This afternoon, I built a little quote app that sits on an e-ink display. It's energy-efficient and easy to read. It updates a few times a minute.

The display is marketed to display your calendar on e-ink. I don't really need that, but I wanted to support a small company, so I bought it. And it sat there for a few months.

For whatever reason, I felt the pull today. And I whipped up an app to serve me quotes based on some of the obvious things I've written up here:

A List of Really Obvious Things
Perhaps the least obvious thing is that the most obvious things are not obvious. Common sense is uncommon. Simple things are hard. Since I discussed this with my friend, Jake, I started writing down obvious things as Ray has written about in Principles. I want to share that with you.

Humans are visual creatures. Spatial creatures. We forget unless it's in our space. So I wanted reminders to center myself back to the things I found important.

I wrote a small Cloudflare Worker to interact with GPT-4 and render the quote into an image. It's not hard but not as easy as it sounds. The normal way to do it isn't possible here because Cloudflare Workers are a special execution environment; there's no concept of a browser. I was even using Workers AI initially to try it out and while I was impressed, the context length was too small. So back to OpenAI it was.

The tricky bit is getting the image to render. There are a lot of them so in an attempt to figure it out, I fiddled with some wasm packages until I found someone had solved it already.

Well, great artists steal. So I imported the workers-og package and was basically done.

import { ImageResponse } from "workers-og";
import OpenAI from 'openai';

export interface Env {
  OPENAI_API_KEY: string;
}

export default {
  async fetch(request, env, ctx): Promise<Response> {
    const openai = new OpenAI({
      apiKey: env.OPENAI_API_KEY,
    });

    let title = '';

	// Generate a random seed integer
	const seed = Math.floor(Math.random() * 1000000); // Adjust the multiplier for different ranges

    try {
      const response = await openai.chat.completions.create({
        model: 'gpt-4-turbo',
        messages: [{
          role: 'user',
          content: `
		  Random seed: ${seed}
		  <your prompt here>
		  `
        }]
      });

      if (response && response.choices && response.choices.length > 0 && response.choices[0].message) {
        const lastMessage = response.choices[0].message;
        title = lastMessage.content || 'An empty string was returned.';
      } else {
        title = 'Error: Unable to generate text response.';
      }
    } catch (error) {
      title = 'Error: Unable to communicate with API.';
    }

    const html = `
      <div style="display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100vh; width: 100vw; font-family: sans-serif; background: #FFF">
        <div style="display: flex; width: 100vw; padding: 40px; color: black;">
          <h1 style="font-size: 40px; font-weight: 600; margin: 0; font-family: 'Garamond'; font-weight: 500">${title}</h1>
        </div>
      </div>
    `;

    return new ImageResponse(html, {
      width: 800,
      height: 480,
    });
  },
} satisfies ExportedHandler<Env>;

Hope you get to try it out.

It was also important to be low-maintenance for me. I wrote some app to do something similar on a plane a few months ago and it ran in a browser window, but I found that annoying as it was hidden behind a bunch of windows and then forgot about it.

I wanted this side project to get better with time. To be in that second bucket of side projects, if you will.

To close, here's a quote I'm looking at now:

Courage in leadership is less about bold actions and more about the quiet removal of fear from those who follow.

Not sure if it's right, but it made me think.

johnny.dev