Software as Art: Making Things in the Age of AI
I recently gave a keynote at next.app devCon in Berlin. After the talk, I was asked whether the content was available anywhere, so I’ve adapted it into a short article here.
AI tools are increasingly shaping the way we do design, engineering, testing, and everything in between. They can help accelerate many manual tasks. But what if you truly care about quality, user experience, and the art of storytelling in software?
I’ve built part of my identity around being good at making software, and I love working on high-quality products. Now I can watch an agent do work I was proud of being able to do, faster than I could, while I’m often also the one asking it to.
It’s hard to pretend that I haven’t questioned whether my skills, or perhaps some aspect of them, are now becoming obsolete. I also know I’m far from being the only one who has experienced this feeling. I’ve spoken with talented engineers who have gone through an identity crisis of sorts. Writing clean code, being opinionated, becoming an expert in a domain, and holding a high bar for quality used to set us apart. At the same time, the accelerating pace of development – or, rather, the ever-increasing expectation of output and optimization – can make it feel like none of that matters anymore.
As more of my work can happen without my involvement, and to a level of quality that seemingly satisfies everyone, what is my value then?
To answer this question, and maybe some others, let’s go back in time.
A memory of home
There’s a memory from my childhood that I can still picture in great detail: walking with my dog through an open meadow at sunset. I remember so many things about it. I remember the tall grasses and wildflowers I had picked so many times, the scattered young pine trees bordering the path, with a dense tree line in the distance of the forest I used to know like the back of my hand. The utility poles recede toward the horizon beneath a softly glowing peach and blue evening sky streaked with gray clouds.
I happen to have a real photo of this scene. But not every memory has a photo; sometimes the memory itself is all we have. Recreating one seemed like a pretty compelling use case for image generation, so I tried describing the meadow to a model.

While reasoning about the prompt, the model made a guess about how I may have wanted the image to feel, not just what I wanted it to look like. It said: “quiet and nostalgic.” I thought that was very accurate, in fact, even though I hadn’t explicitly said anything about how the scene made me feel. Once the image was complete, it notably also included some wildflowers I could remember but didn’t know the names for.
It was a pretty beautiful image, yet it felt wrong. To start with the obvious, the dog in the first generated image wasn’t my dog, because I never specified the breed, so the model went with a sensible default choice.
I corrected the model and kept iterating. I kept adding details as I iterated on the image. At some point, the path wasn’t right. Those poles needed to go from left to right because that particular path curved toward an old church and a lake. Now the plants were a bit tall. Each time, I got closer to the exact scene I had in my head, my own mental reference. In fact, I was realizing that I never would’ve thought to include some of this information in my original prompt. The process of seeing the intermediate results and coming back to my memory was helping me remember more of the details about the place and the time I happened to care so much about.

The image was now very close to what I thought I was looking for, but it still didn’t evoke the same feelings when I looked at it as the memory did. I went through a few iterations, but something wasn’t right. At this point, I had spent enough time thinking about the memory that it didn’t take me long to realize: what I was hoping to express was the feeling of peace, of safety, of a home that doesn’t exist anymore for me.
I hadn’t understood what I cared about in that picture when I wrote the first prompt. The entire time I thought I was negotiating the details with the model, I was actually discovering what it was within myself that I wanted to express.
Marc Chagall painted I and the Village in Paris, drawing on memories of his childhood home. There are upside-down houses in this village, there’s a cow being milked inside the face of another farm animal. To me, it feels true and faithful to a memory, even though it doesn’t look like a place you could ever possibly photograph.

When I was recreating the meadow, I kept trying to make it more accurate, more vivid, more true to life. But this painting makes me think I was looking at the wrong thing. I had gotten myself into a realism trap. Perhaps expressing what home felt like meant making something that looked less like a photograph.
Perhaps some app can meet every functional and nonfunctional requirement, yet still be misguided and thus fail at creating the experience we wanted someone to have when using it.
Perhaps making a great product is not that different from expressing someone’s idea of a childhood home.
Choosing to care
Susan Kare sketched early icons for the original Macintosh on graph paper, with each square representing a pixel. Within those grids of both paper and ruthless technical constraints of early computing, she helped give the computer a friendly, recognizable visual language. The Happy Mac is an absolutely iconic and timeless jewel of that work.

When I look at the original Mac as a product, I see a strong point of view about what a computer could feel like to a person. There’s warmth and humor, and someone making expressive choices within cold technical constraints. Custom typefaces and rounded corners weren’t cut when push came to shove, and neither were the friendly icons and the visual language of the system. It’s hard not to draw parallels and agree that’s quite rare.
There’s a notable gap between the notepad drafts and the final product. Kare’s account of the work describes trying alternatives and letting the designs evolve. The final icons represent a cohesive visual language. You simply cannot get there with a first draft.
The act of expressing an idea, and then iterating to shape it into something another person can experience, is exactly what art is to me, and is also why I believe building software is a form of art, alongside its classical forms.
Software is an expressive medium. Making software is also iterative. Our ideas are the raw material, our paint, our clay, and through iteration, trying things, coming back, and negotiating with ourselves and our environment, we shape it and give it form. If we succeed, the behavior of what we create communicates what we, its creators, value, and expresses the part of us we wanted to put out there for others to experience. A product that really stays with you goes beyond what it does. When you remember it, the first thing you remember is how it felt to use it.
Seeing software as a form of art sounds pretty grandiose, though. The current realities of our industry can make the process feel less like that of a craftsman or an artist, and more like that of a factory worker. To be honest, sometimes I just want to fix some bugs and get through the next product milestone. Sometimes I get burned by the process, things don’t work out, a project I am working on does not turn out exactly how I want – and I feel like I need a break from it all.
Not everything I put out there is my magnum opus. But I don’t think it has to be for what I said about art to be true, and for me to be able to view my work and mission this way. To me, the common thread is simply doing my best to stay intentional: choosing to have a point of view about something every day, however small. Otherwise, there’s no point.
What we choose to care about has to come from somewhere. Sometimes it comes from remembering how it felt to struggle with something and wanting to make that experience better for someone else. It comes from our experiences, our frustrations, the things we admire, and the things we wish existed.
When our team started working on Sky, a Mac app for interfacing with AI more naturally, we wanted the interface to feel like stepping into real fog. You enter something distinct, but you’re still deeply connected to the world around you. On your computer, that meant remaining connected to whatever you were already doing. Your work would still be there, around it. We wanted the interface to feel nonintrusive, almost boundless. The content would stay the same while the colors changed with the desktop. We wanted it to have a presence of its own, while still feeling like it belonged in your space.

To me, this screenshot is part of what makes software such an interesting expressive medium. You can take an object or even something as fleeting as a feeling from the real physical world, something you’ve experienced, and find a way for another person to encounter it through a digital interface. How invigorating is that?! We take an idea, a perspective, give it form through our skills, and put it into the world for other people to experience.
Isn’t that an artistic pursuit?
I want AI tools to help me bring more of what I care about into the work I do. I want it to augment and empower me, not replace me and sidestep my values.
My own journey towards this goal has brought me up against a few challenges. I firmly believe, after having extensive conversations with other engineers and leaders, that most of us have been struggling with a permutation of the same challenges as we’ve been learning to live and work with AI tools.
The feedback loop
At their best, AI tools make it possible to explore things I would’ve put aside before because I simply didn’t have the time. We might start by delegating just enough of the implementation to try an idea out. We may have a good experience while using the tools, and we start leaving more of the decisions to the agent.
Eventually, perhaps, we can delegate the whole product to AI tools end-to-end. We’d simply hand off an idea and get the product on the other end. I’m sure many companies and certain people would be absolutely thrilled about this prospect. Imagine the productivity! Is this what awaits all of us? And if so, does it mean eventual obsolescence for our skills?
This is where my personal definition of art, and what I went through with that illustration of the meadow, come in. The model got me from a description of the meadow to an image very quickly. But the result wasn’t magically my destination. Going through the process was how I discovered what that destination even was.
Giving an idea substance in a way that not only keeps it truthful to my inner world, but also lets the user experience it the way I intended, is not a linear process. It is highly iterative, and the iteration is highly personal and unique to me. The decisions, exploration, even internal (and sometimes external) struggle along the way can stir up and transform the idea itself. The exact same idea will lead to different outcomes depending on who takes this road of bringing it to life.
When I start working on a blank-slate feature for a product, I have an idea of what it should do and how I want it to feel. Then I get into the implementation and, for the first time, I can actually experience something I’ve only been imagining. This process seems like it absolutely could be linear.
For instance, crafting a simple Mac app for capturing a quick note might seem quite linear at first glance: maybe you press a hot key, write something down, and get back to other work. Assume I chose to care about preserving flow state as my product’s philosophy. Then, while testing the implementation, I come back with a new thought and find yesterday’s unfinished note waiting for me. Preserving that note seemed like an obvious choice, but now I have to deal with my previous thought before I can capture my new one, forcing me out of my flow.
Everything might be working exactly as intended from a technical point of view, but returning to a previous idea and capturing a new one turn out to be two different use cases. New experiences, new data, and learnings should and will change what I want to work on next, and oftentimes even how I ultimately choose to view the product, forming a loop from ideation to implementation, and back. A lot of the choices I’m proudest of were ones I couldn’t have made before I started building, so there’s an inherent link between making decisions and carrying them out.
Being able to compress the implementation part of this cycle, iterate on ideas, and learn quickly is a dream come true. But if a decision gets made, I hand it off to an agent, and off I go making more decisions, I lose the link back: the opportunity for what gets built to change the decision I started with. Not all “process” is just mechanical implementation that can or should be delegated away.
I don’t want my relationship with the product to end at writing a prompt and yeeting whatever comes out on the other end out there. I’ve always been very opinionated about not just the product experience, but about the code itself, so learning to delegate has been an especially tough balancing act for me. Much of my judgment has always come from the work of building things and then letting myself be surprised by them. I want to keep learning from what gets built and have a chance to make creative decisions, even if I’m doing less of the building myself. That’s how I’ve defined my role.
Not an ideas guy
Once I found some balance in how I delegated implementation without compromising on my values or quality of output, I slowly began getting some time and capacity back. Only then, I had to decide what to do with that newly acquired time. If you’re a product- or a design-minded person, or someone with more ideas than time to build them, the appeal is pretty clear. But what if writing good code is the part you love?
It’s easy to equate creative choices with coming up with new product ideas, and it may feel like in the AI era your choice is to be more creative with product ideas or become obsolete. Many brilliant engineers I’ve spoken with have deep expertise in a particular area and don’t feel as comfortable branching out. Personally, I’ve also experienced the pressure of a feeling that I should be contributing more original thinking, that my expertise somehow wasn’t enough. But I don’t think we all have to be great at coming up with new product ideas to be great software artists.
Take MacPaint, which has a clear engineering choice behind its interface that you can’t see in a screenshot. In early drawing software, moving part of an image could cause it to flicker by first disappearing from its old position before being redrawn somewhere else as disparate atomic operations. Bill Atkinson prepared the updated image offscreen, in memory, then transferred it to the display when it was ready. I think it matters so much for that perception of continuity, having your task remain uninterrupted by an implementation detail. And to me, that is a creative contribution. An understanding of the internals therefore translates to something the user can experience.
Implementation choices matter just as much as the idea being implemented. Deep expertise lets us see possibilities that wouldn’t occur to someone else. It hasn’t just come to you. You’ve shaped it, internalized it, and made it yours through years of hard work and unique experiences. It gives you ways to shape an experience from inside the implementation. What makes it valuable is how you choose to apply it.
The best way out of this self-imposed crisis of creativity, for me, has been to stop putting pressure on myself to be creative all the time. There’s already creativity in the work I enjoy doing. I don’t have to become a “product guy,” or always be one, to make use of that. I can reach for the things that excite me, and let my mind wander.
Ambition over fatigue
I expected shorter implementation cycles and more opportunities to delegate while preserving meaningful work to afford me more room for that kind of free exploration. Sometimes they did, but iterating more also produced a plethora of smaller decisions that would otherwise have been spread across a much longer timeline. I found myself multitasking more, with more decisions constantly competing for my attention in a never-ending sequence of doom.
This decision fatigue got so bad that I started seeking out opportunities to focus on something that didn’t require making decisions, especially toward the end of a day. What helped was taking the pressure off. I had started treating every spare moment as capacity I was failing to use. Just because you can, in theory, now juggle ten engineering tasks in parallel does not mean you should.
I’d rather use some of that newly found time to try things I used to dismiss as too much work. We’ve spent years learning to estimate what we can realistically build, and those estimates become almost automatic. In many cases, they can dictate whether we take on something in the first place, or whether it forever remains a stretch goal or an unrealistic future project.
As a classic Macintosh nerd, I wanted a weather widget on my e-ink display made with HyperCard. I’d been really into classic Mac emulators for a while, and thought it would be really cool to have a real classic Mac serve a contemporary purpose. But of course, it’s a ridiculous proposition. Classic Mac OS has hardly any of the modern networking stack and none of the modern rendering capabilities. I’d have to reverse engineer this archaic stack and build tools to edit it on my modern machine. Even changing something meant editing inside an emulator, moving a disk image over to the Pi, and restarting things by hand. So I brushed it off.
But a few months ago, I just thought: why not? In a moment of curiosity, I asked an agent to help me close those gaps. And it worked, allowing me to finally focus on the things I cared about: iterating on the UI and the user experience of the widgets.

That moment of curiosity and eventual payoff made me wonder what else I’d ruled out. A strong opinion about how a particular kind of application ought to work can remain a thought experiment for years. After all, who in their right mind would choose to build a UI framework from scratch? At this point in time, I’d question whether the amount of work I associate with exploring an idea like that still holds.
Ambition might mean a new framework for one person or a team. For another, it might mean finally shipping a carefully made app alongside a demanding day job. Something you’ve been carrying around in the back of your mind for years might finally be something you get to make.
I still feel the intentionality in the early Macintosh software I love. That work of making a computer feel friendly and welcoming still means something to me, even though I never got to use the product back when it came out. I’d like my work to do that for someone else.
What makes me excited about collaborating with AI tools is not the soulless productivity, but the possibility that something I care about could become something another person loves, and that the wall separating it from reality is becoming thinner.