From Vibe Coding to Spec-Driven Development

June 24, 20266 min read

Vibe coding is a very natural way to start.

You describe what you want in plain language, the AI writes something, you run it, you adjust the prompt, and the loop continues. For prototypes, experiments, learning, or a small personal tool, this can feel extremely productive.

There is very little ceremony. You can move fast. You can explore an idea before you fully understand it.

That is the good part.

The problem starts when the same style becomes the default way to build software that a team needs to maintain.

The Problem

Software built by a team has different constraints than software built during exploration.

A team needs shared understanding. It needs repeatability. It needs tests. It needs stable behavior across time, people, and changes.

Vibe coding does not naturally optimize for that.

The same prompt can produce different answers. The context can drift during a long chat. A small clarification can change the direction of the implementation. Important edge cases may exist only in the conversation, not in the repository. After a few iterations, it becomes hard to tell what the actual requirement was.

The code exists, but the contract around the code is weak.

That is risky because most long-term software problems are not caused by the first implementation. They are caused by the second, third, and tenth change made by someone who does not have the original context in their head.

Spec-Driven Development

Spec-driven development shifts the starting point.

Instead of asking the AI to immediately build something, you first describe what should be true.

What is the expected behavior?
What are the inputs and outputs?
What are the constraints?
What should happen when something fails?
Which edge cases matter?
What is explicitly out of scope?

Then the AI can help generate requirements, design, implementation, and tests from that specification.

The important difference is not that AI disappears from the workflow. The difference is that AI is no longer guessing from a vague conversation. It is working against a written contract.

That contract becomes useful for humans too.

A new engineer can read it. A reviewer can compare the implementation against it. A test can be derived from it. A future refactor can preserve it.

The spec becomes the source of alignment.

This Is Not New

Before AI, we already had versions of this.

Requirements, design, implementation, test, deploy.

In practice, modern teams rarely run this as a strict waterfall process anymore. Work is split into smaller iterations. Requirements evolve. Designs change. Teams learn while building.

But the basic idea was still valuable: before implementation, create enough shared understanding to reduce expensive ambiguity later.

AI did not remove that need.

If anything, AI makes it more important.

Because AI makes it easier to produce code quickly, it also makes it easier to produce code before the team understands the problem clearly.

That speed is useful, but only if the direction is right.

Where Vibe Coding Fits

I do not think vibe coding is bad.

It is a great exploration tool.

Use it to test an idea.
Use it to learn an unfamiliar API.
Use it to generate a throwaway prototype.
Use it when the cost of being wrong is low.

But when the work crosses into shared systems, production behavior, customer impact, security, migrations, or long-term maintenance, the workflow needs more structure.

At that point, the question should not be:

Can the AI generate the code?

The better question is:

Do we have a clear enough specification to know whether the generated code is correct?

That is the real boundary.

A Practical Workflow

The version I trust more looks like this:

  1. Write the specification first.
  2. Ask AI to find missing cases or unclear requirements.
  3. Refine the spec.
  4. Generate a design from the spec.
  5. Review the design before implementation.
  6. Generate the implementation.
  7. Generate tests from the same spec.
  8. Compare the final result back to the original contract.

The model can help at every step.

But the team still owns the specification, the tradeoffs, and the final judgment.

That is the part I do not want to outsource.

A Concrete Example

A good example of this approach is the spec-driven development skill from Addy Osmani's agent-skills repository.

The workflow is simple, but important:

SPECIFY → PLAN → TASKS → IMPLEMENT

The interesting part is not the diagram. The interesting part is the gate between each step.

The AI does not jump from an idea directly into code. First, it writes down the assumptions it is making. For example: this is a web application, the database is PostgreSQL, authentication uses sessions, or the target is modern browsers only.

That sounds small, but it changes the quality of the interaction.

Instead of hiding uncertainty inside the implementation, the AI exposes it before the implementation starts.

Then the vague request is translated into testable success criteria.

For example, “make the dashboard faster” is not a good engineering target. It can mean many things. A better spec would say something like:

  • Dashboard LCP should be under 2.5 seconds on a 4G connection.
  • Initial data load should complete in under 500ms.
  • The page should not shift during loading.

Now the team has something reviewable. The AI can still help, but the target is no longer vibes. It is a contract.

I also like the boundary model in that example:

  • Always do: run tests, follow naming conventions, validate inputs.
  • Ask first: change database schema, add dependencies, modify CI.
  • Never do: commit secrets, edit vendor directories, remove failing tests without approval.

This is the part teams often miss when they adopt AI coding tools.

They define what the AI should build, but not what the AI is allowed to change.

For me, this is where spec-driven development becomes more than documentation. It becomes an operating model for AI-assisted engineering.

The Takeaway

Vibe coding is optimized for momentum.

Spec-driven development is optimized for alignment.

Both are useful, but they solve different problems.

For individual exploration, momentum may be enough. For team software, alignment is usually the harder and more valuable thing.

The future of AI-assisted development is probably not just better prompts. It is better contracts around the prompts.

Clear specs. Explicit constraints. Deterministic tests. Human review.

Not because we want to slow AI down.

Because we want the speed to compound instead of turning into maintenance debt.