API Clients & Data Access Boundaries

Keep HTTP concerns out of every UI component. A dedicated data-access layer can handle URL construction, authentication headers, parsing, retries, and typed responses.

Components should ideally ask for domain operations rather than know every transport detail. This improves testability and makes migrations easier.

Still, do not over-engineer a thin wrapper around fetch if the application has only a few endpoints. Introduce an abstraction when it provides a meaningful boundary.

Domain API function
export async function getUser(id: string): Promise<User> {
  const response = await fetch(`/api/users/${id}`);
  if (!response.ok) throw new Error("Failed to load user");
  return response.json();
}
💡 The component can consume a domain operation without knowing how the URL or response parsing works.
Key Takeaways
  • Centralize repeated transport behavior.
  • Expose domain-oriented operations where useful.
  • Avoid abstractions that do not reduce complexity.