Software is user action
There are two places to get stuck in software development.
The first is building something in your head. Beginners often get stuck here. You dream up a perfect theoretical system, but it's too big to squeeze through the toothpaste tube of your actual abilities.
The second is building something complete. Experienced programmers often get stuck here. You build a system, but your vision for it never quite matches the elegance of what you imagined. You're always just one big feature or one big refactor away from perfection. Your project grows in its ambitions, day by day, until you're crushed under its weight.
The secret is to realize that the unit of work in software development is not specs, designs, or plans of any kind. It's working software.
Just as a painting is composed of paint, software is composed of motion.
In software development, the paint is your users' brushstrokes
A user moves a card, presses a button, turns a dial, and something happens on the screen. That "something happens" is the atom. You cannot see it clearly before you build it, and you cannot build it correctly before someone uses it.
There's a temptation, especially in the age of AI, to believe a complete system is possible without using and refining each part before you build on top of it. AI can generate UI, endpoints, and modules quickly. It can make a system look complete before it has earned any right to exist.
But a document-editing app is not "a WYSIWYG editor plus an API endpoint." It's everything in between.
- Is the text Markdown or rich text?
- Is the focus of the UI information density or readable typography?
- Do you allow every type of document or are you focused on one use case?
Those decisions matter at every level of the user experience. They are not garnish. They determine whether each feature is discoverable, understandable, and trustworthy. And the best way to make sure they are is to grow a system organically, piece by piece, watching how they're used.
The brushstroke is the flow of using the feature. You can't see the brushstroke before someone uses it.
Here's the point where I'm getting stuck right now: AI helps you build instead of over-planning. That's real. But on the flip side, it can push you into the false trap of thinking your project's complete too early. You end up with a feature-packed, self-consistent, operational system that no one uses.
People don't understand how to use it, so features remain undiscovered. Or features are discovered and they break in weird ways as soon as they touch real workflows.
But the above is solvable with feedback. The worst part about working alongside AI is that once your users report an issue, it's much harder to adapt and change direction. There's so much of the system that AI has built that you don't understand. You can't modify it confidently, so it can't adapt. And software is meant to move, grow, and adapt.
I don't think the solution is "don't use AI." It's "use AI for one feature at a time, and have someone use it before you build on top of it."
Here's how I do it in practice:
- Pick a small part of a project I can share
- Set a timer (60–120 minutes) and finish with something that runs
- Make "shareable" part of the definition of done (a URL, a file, a demo video)
- Show one person and see how they experience it
A few rules I keep coming back to:
- You can't build products in the dark. You need to use it and ideally get someone else to use it.
- You can't build for everyone and every use case.
- A feature-packed system doesn't matter on its own. It needs to grow with the market, grow with its users, and adapt to the ecosystem it's in.
- The paint is usable prototypes, not API endpoints or designs.
When software is allowed to grow this way, it becomes real. It earns its completeness by moving and adapting the way people expect it to move and adapt to them. That's what "complete" should mean. Let users do one thing at a time, and do it well. Each brushstroke should flow naturally from the one that came before it.