FireUX · 2 min

Build a Second Example Before an Abstraction

A second real product example reveals which parts of an architecture are genuinely shared and which only looked reusable in the first version.

Build a Second Example Before an Abstraction

Build a Second Example Before an Abstraction

The first working version of a feature can make its structure feel universal. Names are clean, boundaries look obvious and several helpers appear reusable. Then a second real product arrives and asks different questions.

That is not an inconvenience. It is the evidence an abstraction needs.

One example proves a product, not a family

A successful first implementation proves that one named product can work. It does not prove that every folder, option or component belongs in a shared framework.

Extracting too early often produces a configurable engine built around the assumptions of the first member. The second member then requires branches, optional properties and exceptions. Reuse increases on paper while comprehension falls.

Use a proving sibling

Our preferred sequence is:

  1. Complete one independently useful baseline.
  2. Create a second real member with its own product purpose and ownership.
  3. Reuse fundamentals already justified by security, accessibility or domain truth.
  4. Let the second member develop a material difference.
  5. Compare what remains shared for the same reason.
  6. Promote and guard only that surviving contract.

The second member may begin with a bounded structural copy. Duplication at this stage is construction, not proof. A renamed alias, theme swap or fixture is not enough; the sibling must be independently editable and face a genuine product requirement.

Share fundamentals without predicting everything

Waiting for evidence does not mean rebuilding known basics. Authorization, identity, readiness, accessibility and safe transport can be shared from the beginning when their reasons are already established.

What stays named is the uncertain product seam. useKitchenCollection and useCompanyCollection, for example, can share lower read mechanics without pretending their filters, authority and outcomes are identical.

What we do at FireUX

FireUX describes family growth as baseline, proving sibling, differentiation and established spine. We keep member entrypoints named while comparison is still useful. A contract becomes shared only after real members continue to need it for the same reason.

This approach works especially well with AI-assisted development. The agent receives an explicit comparison instead of an invitation to generate a generic framework from one attractive implementation.

Our related article on aligning contracts rather than every interface explains what to compare once those siblings exist.

The small amount of deliberate repetition is usually cheaper than maintaining the wrong abstraction for years.