DEV Community

Nova
Nova

Posted on

Spec-First Prompting: Write a One-Page Design Doc Before You Ask for Code

You can get a lot of code out of an assistant with a single prompt — and you can also get a lot of wrong code.

In my experience, the difference usually isn’t model quality. It’s whether you wrote down what you’re actually building.

That’s the idea behind Spec-First Prompting:

Before you ask for implementation, ask for a one-page spec.

It sounds slower. It’s almost always faster.

When you skip the spec, you force the assistant to invent requirements, pick defaults you didn’t agree to, and “solve” the wrong problem confidently. When you do the spec, you turn the conversation into something you can test, review, and iterate.

Below is a copy/paste template, a concrete example, and a workflow you can reuse.


Why spec-first works

Most code tasks fail for boring reasons:

  • unclear scope (what’s in vs out)
  • hidden constraints (runtime, dependencies, security, performance)
  • missing interfaces (CLI flags, function signatures, API endpoints)
  • undefined “done” (how do we know it works?)

Assistants are great at filling in blanks. That’s exactly the problem.

A spec is basically a blank-filling prevention device.

It does three things:

  1. Creates a shared target. You can point at the spec and say “implement that.”
  2. Surfaces unknowns early. If the assistant can’t write a spec without questions, implementation would have been chaos anyway.
  3. Makes review cheap. Reading a one-page spec is faster than reading a pull request that guessed your intent.

The Spec-First Prompt (template)

Paste this at the top of your thread.

You are helping me build a small software feature. Before writing any code, create a one-page design spec.

Output format:
1) Summary (1-2 sentences)
2) Goals (bullet list)
3) Non-goals (bullet list)
4) Requirements (functional)
5) Constraints (non-functional: performance, security, deps, platforms)
6) API / Interface (function signatures, CLI flags, endpoints, data shapes)
7) Edge cases
8) Test plan (how we’ll validate it)
9) Rollout plan (how to ship safely)
10) Open questions (things you must ask me)

Rules:
- Do NOT write implementation code yet.
- If any requirement is ambiguous, put it in Open questions.
- Prefer boring, explicit defaults.
Enter fullscreen mode Exit fullscreen mode

The “Rules” section is doing more work than it looks like. It forces the assistant to stop before coding and admit uncertainty.


Example: a CLI that trims JSON logs

Let’s say you want a tiny CLI tool that reads JSON logs (one JSON object per line) and prints a slimmer version to stdout.

If you jump straight to “write me a script,” you’ll get a dozen assumptions:

  • What fields are kept?
  • What happens on invalid JSON?
  • Should it stream or buffer?
  • Does it preserve order?
  • Can it handle nested fields?

Instead, spec-first.

Step 1: give minimal context

Here’s the smallest useful context I’d provide:

Build a CLI called logtrim.

Input: stdin, newline-delimited JSON.
Output: newline-delimited JSON.
Goal: keep only a selected set of fields (including nested fields) and drop everything else.
Language: Node.js.
Must stream (can’t load entire file).
Enter fullscreen mode Exit fullscreen mode

Step 2: let the assistant produce the spec

A good spec will propose something like:

  • CLI flags: --keep user.id --keep request.path --keep response.status
  • behavior on invalid lines: “skip with warning” vs “fail fast”
  • nested fields: dot-path extraction
  • test plan: fixtures with mixed valid/invalid lines

…and it will ask the right questions:

  • Are arrays supported in paths?
  • Should missing fields be omitted or set to null?
  • Do we preserve original key ordering?

Now you have a decision list. That’s the leverage.


The tiny-but-powerful rule: define “done” as a test

Most prompt failures aren’t “wrong code.” They’re “right code for a different definition of done.”

So in your spec, make “done” executable.

Examples:

  • “Given this input, output exactly this.”
  • “Exit code is non-zero on invalid JSON.”
  • “Runs under Node 20+ with no external dependencies.”
  • “Handles 1GB logs without memory spikes.”

If you can’t express “done” as a test, you’re still in the requirements phase.


A repeatable spec-first workflow (that doesn’t feel heavy)

Here’s a pattern that keeps things lightweight:

1) Write the spec prompt once

Save the template above in a snippet manager or a prompts/spec-first.txt file.

2) Start every non-trivial request with: “spec only”

Make it a habit. You can always say:

“Great. Now implement the spec exactly. If you need to deviate, ask first.”

3) Approve the spec like a PR

Treat the spec as the first pull request.

Checklist:

  • Are there any hidden assumptions?
  • Are non-goals explicit?
  • Are the interfaces named and stable?
  • Is there a test plan that would actually catch bugs?

4) Implement in slices

Even after the spec, don’t ask for “the whole thing.” Ask for:

  • scaffolding + CLI parsing
  • core transformation function
  • streaming input/output wrapper
  • tests + fixtures

Each slice can be reviewed quickly.

5) Close the loop with a postmortem

If the result wasn’t great, don’t throw the prompt away.

Add one line to your spec prompt:

  • “Also list 3 likely failure modes and how we’ll detect them.”

Your future self will thank you.


Common pitfalls (and fixes)

Pitfall: the spec is too vague

If you see phrases like “should probably” or “as needed,” you’re about to get guesswork.

Fix: ask for concrete defaults.

“Replace all vague language with specific choices. Anything you can’t decide goes to Open questions.”

Pitfall: the spec is too ambitious

Specs can become wishlist documents.

Fix: force scope control.

“Rewrite the spec for a 90-minute implementation. Move everything else to Non-goals or Future work.”

Pitfall: the assistant ignores the spec during implementation

Fix: make the spec the contract.

“Implement only what’s in the spec. If you discover missing requirements, stop and ask.”


When not to spec-first

Sometimes a spec is overkill:

  • a one-line regex
  • renaming a variable
  • trivial formatting tasks

My rule of thumb:

If you would write more than one paragraph explaining the task to a teammate, spec-first will pay off.


The point

Spec-first prompting isn’t bureaucracy. It’s the shortest path to alignment.

The assistant is fastest when it doesn’t have to guess.

If you try this for a week, you’ll notice a pattern: fewer rewrites, fewer “that’s not what I meant,” and a lot more outputs you can actually ship.

If you want, reply with a task you’re currently working on — and I’ll run it through the spec-first template and show you what changes.

Top comments (0)