Skip to main content
Specifications is coming soon. This documentation previews what the section will look like at launch.
Specifications are most useful when they are precise where it matters and vague where it does not. This page covers the heuristics that lead to good specs and good generated code.

Be precise about behavior, not implementation

A good spec describes what should happen, not how. “When a user submits an order, charge their card and send a confirmation email” is precise behavior. “Use Stripe’s Charge API with idempotency keys, then call SendGrid’s templates endpoint” is implementation — Archie picks the right implementation from the integrations in your plan. Implementation detail in a spec is fragile: if you change the integration in the plan, your spec is out of date. Behavior in a spec is durable.

Write copy first, design later

Copy in the spec is one of the highest-leverage edits you can make. Specifying button text, placeholder text, and error messages upfront removes a whole round of “the button says the wrong thing” edits after the build. Visual design (font, color, spacing) does not belong in the spec. It belongs in Frontend theming.

Name edge cases explicitly

The fastest way to ship a broken feature is to leave edge cases unspecified. Empty states, network failures, race conditions, large datasets, permission boundaries — name each one and describe what should happen. The spec format encourages this: each feature has an “Edge cases” section with structured prompts. Use them.

Be vague about non-decisions

Not everything needs precision. If you do not have a strong opinion on whether the order list shows 20 or 50 items per page, leave it unspecified. Archie picks a reasonable default based on the feature type and the data shape. Over-specification creates work without value. The spec is for things you care about; defaults handle the rest.

Match the spec’s granularity to the feature

Some features are simple (a profile page) and need a short spec. Others are complex (a multi-step checkout) and need detailed flows, edge cases, and copy. Use the granularity that matches the feature, not a fixed template. If a spec is taking a long time to write and the feature is straightforward, you are over-specifying. If a spec is short and the feature is complex, you are likely missing detail that will surface as bugs later.

Spec the unhappy paths

The happy path is usually obvious. The unhappy paths are where products break:
  • What happens when the network drops mid-action?
  • What happens when two users edit the same record at the same time?
  • What happens when a payment fails after the user navigates away?
  • What happens when a permission boundary blocks an action mid-flow?
Spec these explicitly. Generated code will handle them with concrete logic instead of guessing.

Iterate the plan, not the spec

If you find yourself writing the same edit across many specs (“on every list, allow filtering by status”), promote the change to the plan. Cross-cutting changes belong at the plan level — modules, user types, services, integrations. The plan cascades to specs automatically.

Review specs as a team

Specifications are designed to be readable by non-developers. Use that. Have a product manager or designer review the spec before you build. Catching a misunderstanding in the spec is much cheaper than catching it in deployed code. For team workflows, version each spec change with a comment (“aligned with PM on canceling logic”) so future readers understand the why. See Editing specifications for the version history.