Long before we began the serious development work that eventually became PageSnip and ProHelp Studio, I had already become interested in the idea of adding a capable Markdown editor to some of our software.
So I did what many developers would do today.
I asked AI to help me build one.
It worked.
In fact, that early editor did exactly what I needed it to do at the time.
I could experiment with Markdown editing.
I could try different ideas.
I could see what was possible.
I could begin discovering which capabilities mattered to me and which ones did not.
AI got me from an idea to something tangible remarkably quickly.
That early editor was not a failure.
It was a successful prototype.
The distinction matters.
The first question was "Can we do this?"
At the beginning, I was exploring.
I didn't yet have a large set of requirements.
I wasn't trying to build a Markdown editing surface that several of our products would eventually depend upon.
I was trying to answer simpler questions.
Can we do this?
What might it look like?
How would it feel inside one of our applications?
Which features are genuinely useful?
For those questions, AI-generated software was ideal.
The cost of experimentation had dropped dramatically.
Instead of spending days or weeks building enough infrastructure to evaluate the idea, I could start using something almost immediately.
That is one of AI's great strengths in software development.
It makes curiosity inexpensive.
Then the requirements changed.
A prototype became infrastructure
As PageSnip developed, Markdown stopped being an experiment.
We needed a serious editing and rendering surface.
Similar requirements emerged as we worked on ProHelp Studio and other products.
Now the question was no longer simply whether we could display and edit Markdown.
The Markdown surface had become part of our infrastructure.
That changed everything.
Instead of simply asking AI to invent another editor for us, we spent considerable time evaluating mature technology and deciding what we actually wanted to build around.
This was an incredibly important process that was worth doing.
Then we began integrating it into real products.
That's where product development started teaching us things the original prototype never could.
Requirements we did not know we had
A Markdown editor sounds like a reasonably well-defined problem.
Until you depend upon one.
Then the questions begin multiplying.
How should the editing surface behave with large documents?
What happens in Rich Text mode?
How does typing performance hold up after additional processing is introduced?
Do tables behave consistently?
Does what appears on screen also print correctly?
Does PDF output follow the same rules?
What happens with literal Markdown constructs that resemble something else to the renderer?
Does a fix belong in one application, or does it really belong down in the shared rendering layer?
If we patch something with local JavaScript or CSS, are we fixing the problem or merely hiding it on one surface?
Will the same content behave consistently when it appears in PageSnip, ProHelp Studio, ProHelp Viewer, and other applications built on the same foundation?
These are not theoretical concerns.
They are the kinds of things you discover when software stops being a demonstration and starts becoming something you use every day.
Most importantly, many of them were requirements I could not have included in my original AI prompt.
I didn't know enough to ask for them yet.
That may be one of the most important differences between prototyping and product development.
The hardest requirements are often the ones you don't know enough to put in the first prompt.
Then we came back to the original editor
Eventually we reached an interesting point.
The work we had done inside PageSnip, ProHelp Studio, and our other applications had matured enough that we wanted to bring those capabilities back down into our component-level products.
In other words, we wanted technology we had been refining for our own applications to become available for other developers to use in theirs.
At that point, we still had the original AI-engineered Markdown editor.
There was an obvious path available.
Improve it.
Take what we had learned and begin adding those capabilities to the older component.
Refactor it.
Modernize it.
Fix its weaknesses.
AI could certainly have done all of those things.
In fact, that was precisely the problem.
The AI recommended that we rip it out
When we did a deeper architectural analysis of the backport, AI recommended something much more drastic.
Do not improve the old editor.
Remove it.
Completely.
That recommendation turned out to be one of the most important decisions in the process.
The reason was not that the old editor was terrible.
The reason was that it represented a different evolutionary path.
If we kept it, the natural tendency of subsequent AI-assisted development would be to make the thing already in front of us better.
That sounds perfectly reasonable.
But we would have ended up maintaining two different answers to the same problem.
One Markdown architecture inside the applications we had spent months refining.
Another Markdown architecture inside the component product, steadily improved from the older prototype.
Both might eventually have become good.
But they wouldn't have been the same.
Their behavior would diverge.
Their fixes would diverge.
Their edge cases would diverge.
And the component we ultimately offered to other developers would have been a lesser product than the technology we were already relying upon ourselves.
So we did something that can feel uncomfortable in software development.
We threw away working code.
AI is very good at improving what already exists
This experience taught me something else about AI-assisted development.
AI is remarkably good at local optimization.
Show it an existing implementation and ask for an improvement, and it will naturally try to preserve as much of the current structure as possible while solving the problem you gave it.
Usually, that is exactly what you want.
You do not want every bug fix to trigger a complete rewrite.
But sometimes the existing code itself has become the constraint.
In that situation, asking:
How can we make this better?
may be the wrong question.
A better question is:
Should this implementation continue to exist?
In our case, AI participated in answering that question.
The answer was no.
That is an important part of the story because this was not a case of a human developer deciding that AI-generated code was bad and throwing it away.
AI helped us recognize that continually improving its earlier work would lead us toward the wrong product.
Sometimes the best contribution AI can make to a codebase is recommending that some of the code disappear.
AI makes the wrong road cheaper too
There is a larger lesson here.
AI makes software development faster.
But speed is neutral.
It makes the right road cheaper.
It also makes the wrong road cheaper.
Before AI, an inferior architecture often revealed itself because adding new capabilities became painfully expensive.
Today AI can keep a mediocre architecture alive for a surprisingly long time.
It can patch around limitations.
Refactor awkward pieces.
Generate adapters.
Add tests.
Repair regressions.
And because every individual improvement is relatively inexpensive, it can become easy to keep moving forward without asking whether the underlying direction still makes sense.
You can become extremely productive while traveling toward the wrong destination.
That's why architectural questions become more important, not less, when AI writes the code.
The product was everything we learned after the prototype
By the time we brought the Markdown work back to the component level, the value was no longer simply that we knew how to place a Markdown editor in an application.
AI had already demonstrated that much with the original prototype.
The value was everything that had happened since.
We had chosen the underlying technology deliberately.
We had used it inside real applications that had thousands of hours of flight time on them.
We had encountered edge cases.
We had found regressions.
We had learned which fixes belonged locally and which belonged in shared infrastructure.
We had discovered performance constraints.
We had forced rendering, editing, printing, and other output surfaces to behave consistently.
Then when our own applications exposed another weakness, the shared technology improved again.
Somewhere along the way, we stopped merely building a Markdown editor.
We were building confidence in one.
That is the distinction that eventually led us to a phrase we use for our component products:
"Built for our products. Available for yours."
The important part is the first half.
We're not creating a component simply because we think somebody might buy it.
We're taking technology our own products already depend upon and making it available to other developers.
The component inherits everything those products forced us to learn.
The prototype still mattered
I would not go back and eliminate that first AI-generated editor from the story.
It was valuable.
It helped me explore the idea.
It helped me understand the problem.
It helped establish that Markdown editing was something worth pursuing.
It did exactly what a good prototype should do.
But prototypes and products answer different questions.
The prototype answered:
Can we build this?
The product had to answer:
Can we depend upon this?
AI can help enormously with both questions.
The mistake is assuming they are the same question.
They aren't.
And perhaps that is one of the larger lessons of AI-assisted software development.
AI can give us answers astonishingly quickly.
Serious product development is often the longer process of discovering which questions still need to be asked.
Related guide
When Code Becomes Cheap, What Are Software Companies Selling?