I / Field notes

Six React foundation decisions to make before feature delivery accelerates

A practical way to establish the few frontend decisions that make later React delivery safer, more consistent, and easier for another team to own.

  • React architecture
  • Product foundations
  • Ownership transfer

A durable React foundation is not a long list of libraries. It is a small set of decisions that keeps product work coherent when more features, developers, and integrations arrive.

The goal is not to predict every future requirement. It is to remove ambiguity from the decisions that will otherwise be made differently in every feature—and to prove those decisions in one representative path through the product.

I-01

Evaluate decisions by reach and reversibility

Not every choice deserves foundation-level attention. Score a decision against four questions:

  • Reach: how many features or teams will depend on it?
  • Reversibility: can it be changed incrementally without coordinating the whole product?
  • Failure cost: what happens when the decision is wrong in production?
  • Ownership: will the team receiving the product understand and evolve it?

A high-reach, hard-to-reverse decision belongs in the foundation. A local and easily replaced choice belongs in the feature that needs it. This distinction prevents a foundation project from becoming a speculative platform programme.

I-02

1. Draw the responsibility boundaries

Make the main frontend responsibilities visible before choosing folder names. A useful boundary map shows where route composition, feature behavior, domain rules, API adaptation, shared UI, and platform concerns belong.

The test is explanatory rather than aesthetic: a developer should be able to place new behavior and state why that layer owns it. If the answer depends on who happens to implement the ticket, the boundary is not yet useful.

I-03

2. Assign data and state ownership

Separate server-owned data, URL state, form state, transient interface state, and genuinely shared client state. Define where each is read, transformed, cached, invalidated, and reset.

This decision avoids two costly extremes: fetching the same server data through several client abstractions, or centralizing local interaction state in a global store. The correct model follows the lifetime and authority of the data, not the convenience of a single API.

I-04

3. Design loading, empty, failure, and recovery paths

The happy path is not a complete feature contract. Decide how route-level loading, partial loading, empty results, validation failure, authorization failure, provider failure, and retry should behave.

These states affect component boundaries and data flow. Designing them after the happy path often exposes that the original abstraction cannot represent the real product behavior cleanly.

I-05

4. Give each test layer a responsibility

Testing strategy should answer which risks are protected where. Pure domain rules, component behavior, integration contracts, and a small number of critical user journeys do not need the same tool or scope.

The foundation should provide representative examples and clear selection criteria, not a target number of tests. Coverage is useful as a signal only when the tests protect behavior the team understands and intends to maintain.

I-06

5. Establish the reusable UI boundary

Define how semantic tokens, accessible primitives, product components, and feature-specific composition relate. A button or field belongs in the shared system when its behavior and visual contract are stable across contexts. A complex product panel usually belongs close to the feature until repetition proves otherwise.

This avoids both uncontrolled duplication and a design system filled with premature abstractions. Reuse should follow demonstrated sameness, not visual resemblance alone.

I-07

6. Make operability part of the architecture

Decide what must be observable when the product fails: route errors, important provider failures, performance regressions, and meaningful conversion events. Set privacy boundaries at the same time so personal data, tokens, and form content do not enter logs or analytics by accident.

Also define the delivery path: environments, configuration ownership, release checks, rollback expectations, and who receives production signals. A frontend that can be built but not confidently operated is not a complete foundation.

I-08

Prove the foundation with a vertical slice

The best validation is one representative feature that crosses the real boundaries: routing, data access, validation, interaction, failure states, reusable UI, tests, observability, and deployment. Use it to reveal where the written decisions are awkward or incomplete.

The output should be compact and executable:

  • A boundary map that names responsibilities and dependency direction.
  • A short decision record for each high-reach choice and its trade-offs.
  • One implemented vertical slice that developers can inspect and extend.
  • Representative component, integration, and testing patterns.
  • A handover session in which the receiving team changes the slice themselves.

The foundation is ready when it reduces the number of decisions hidden inside the next feature—not when every possible abstraction has been built.

I-09

Where this fits

Build on Strong Foundations applies this approach from approved product and design direction through a production-ready React frontend, with deliberate transfer to the team that will own it next.

Explore Build on Strong Foundations