api-library-design

Installation
SKILL.md

API & Library Design

Core principle: friendly, consistent, discoverable

A public API should be usable by someone reading only the function signatures and a few examples — without needing to read the implementation. Consistency across the whole library matters more than any single function being clever.

Naming conventions

  • Be consistent across the entire package: if one constructor is New(...), don't have another be Create(...) or NewFoo(...) unless there's a real reason for the difference (e.g., multiple constructors for different configurations — NewWithConfig, NewFromFile).
  • Match Go stdlib naming instincts: New for constructors, Must* for a variant that panics instead of returning an error (used sparingly, and only when the panic is genuinely appropriate — e.g. package-level setup that can't reasonably continue), With* for functional options.
  • Avoid stutter: kyu.Queue, not kyu.KyuQueue. Package name + type name should read naturally together at the call site (kyu.New(), not kyu.NewKyu()).
  • Prefer verbs for functions/methods and nouns for types — queue.Enqueue(job), not queue.Job(job).
  • Name things for what they do, not how they're implemented. RateLimiter.Allow() not RateLimiter.CheckTokenBucket() — the token bucket is an implementation detail, not part of the contract.

Exposing configuration

  • Default to the functional options pattern for anything with more than 2-3 optional configuration values — it keeps the zero-config case simple (kyu.New() just works) while letting advanced users opt into more control (kyu.New(kyu.WithRetries(3), kyu.WithBackoff(...))).
  • Every option should have a sane default that works for the common case without the caller needing to know it exists. A library that requires reading the docs before it does anything useful has failed the "friendly" bar.
  • Don't expose internal configuration that callers can't meaningfully act on — if a config value only matters for your own testing/debugging, keep it unexported.
  • Struct-based config (a Config struct passed to New) is a reasonable alternative to functional options when the config is fixed and unlikely to grow — pick whichever fits the library's actual shape, but be consistent within one library.
Installs
1
GitHub Stars
32
First Seen
Oct 17, 2026