Skip to content

Instantly share code, notes, and snippets.

@eonist
Created March 29, 2026 10:26
Show Gist options
  • Select an option

  • Save eonist/f0ae6cff91c8847c64ed584fd9953a90 to your computer and use it in GitHub Desktop.

Select an option

Save eonist/f0ae6cff91c8847c64ed584fd9953a90 to your computer and use it in GitHub Desktop.
feature spec.md

[Feature] spec

Covers src/path/to/module.ts — one sentence describing what this module does and why it exists.


Why we write specs

Code tells you how something works. A spec tells you what it is supposed to do — and those two things are not always the same.

Without a spec, the only way to understand intended behaviour is to read the implementation and guess which parts are deliberate and which are accidents. Reviews become slower, regressions are harder to catch, and edge cases live only in the memory of whoever wrote the original code.

A spec solves this by making behaviour an explicit, reviewable artefact:

  • It is the source of truth for intent. When implementation and spec disagree, that is a bug or an outdated spec — either way, something needs fixing.
  • It makes reviews faster. A reviewer can check behaviour against the spec rather than reconstructing intent from code.
  • It protects against regressions. Behaviour that is written down is harder to silently break across refactors.
  • It onboards new contributors. Anyone can understand what a module does without reading every branch.
  • It surfaces design decisions. Deliberate asymmetries, guard conditions, and non-obvious rules are documented where they belong — next to the behaviour they govern.

What a spec is not

  • Not a test suite — specs describe intent, tests verify it.
  • Not API documentation — specs describe runtime behaviour, not public interfaces.
  • Not a changelog — specs reflect the current intended state, not history.
  • Not implementation comments — specs live in spec/, not in the source file.

How to use this template

  1. Copy this file into the subfolder that matches your domain (auth/, editor/, data/, ui/, images/, pwa/, features/).
  2. Name it in kebab-case matching the primary concept (e.g. rename.md, guest-gists.md).
  3. Fill in each section. Delete sections that do not apply — a short precise spec beats a long incomplete one.
  4. Add an entry for the new file in spec/README.md.
  5. Submit the spec in the same PR as the behaviour it describes. Keeping them together is what makes specs trustworthy.

[Primary behaviour or lifecycle]

Event / condition Expected behaviour
[trigger A] [what happens]
[trigger B] [what happens]

[State or mode variations]

  • When [flag/condition] is true: [behaviour]
  • When [flag/condition] is false (default): [behaviour]

[Named sub-flow or algorithm]

1. [Step one]
2. [Step two]
3. [Step three]

[Edge cases and constraints]

  • [Condition] is skipped / ignored / a no-op.
  • On failure: [what happens — logged, thrown, retried?].
  • [Symbol] is the single source of truth for [concept]; do not duplicate it.

[Error states]

Condition Behaviour
[network / API error] [how the UI or data layer responds]
[invalid input] [validation result]

Note: [Optional — use this blockquote pattern only for deliberate asymmetries, non-obvious design choices, or important caveats that a reviewer might otherwise flag as a bug.]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment