One way to communicate
Using one approach removes a recurring decision from feature work. You do not need to decide whether a list should use an API while its form uses a Server Action, or explain why two similar operations cross the backend boundary in different ways. The convention is straightforward:- Client components call a typed service from
src/services/api/. - The service calls a route under
src/app/api/. - The route authenticates, authorizes, validates, and handles the operation.
- The route returns a standard success, error, or paginated response.
Why APIs
APIs create a clear separation between the frontend and backend. They are also a generally understood boundary, regardless of whether someone comes from a React, mobile, backend, or another application-development background. That boundary keeps future options open. A mobile application, another product, an integration, or an agent can consume the same backend entry points without requiring the original React component tree.The API-first convention does not prevent you from using Server Components.
When a Server Component passes data to a Client Component, it uses the same
serializers and public types as an API response.
Frontend API services
Components do not callfetch directly. API calls live in typed service objects
such as:
Standard responses
Route handlers use the helpers insrc/app/api/response.ts. Successful
responses expose data consistently, paginated responses add pagination
metadata, and errors use a shared error shape.