React SPA architecture · Build
One way to fetch data and refresh sessions in your React SPA
If each feature in your SPA fetches data and handles sessions its own way, we give each concern its own layer, and build checks keep features on those layers.
EngagementHourly · remote
Hours9–18 CET · 4 h overlap
StackReact · TypeScript · Vite
Proof3 case studies
The service in 4 parts
01 · Who it’s for
A team whose React single-page app grew one feature at a time, until each feature fetched data, cached it and dealt with an expired session in its own way.
02 · What we’ve built
- Our own design system has three targets: a Vite SPA, Next.js and React Native. The call that renders the login screen is the same, byte for byte, in all of them.Case study 01 →
- The system’s 678 tests include a separate SPA target, and every CI run does a real Vite build alongside the Next.js and Metro builds.Case study 01 →
- React and Redux dashboards for five kinds of user on a US marketplace. Each user type got its own branch of the router, /dashboard/{user_type}/{page}, so role checks didn’t spread through the components.Case study 08 →
- On the same marketplace, build rules made every API call declare its request and response types and kept each component at 200 lines or fewer.Case study 03 →
No client paid for the design system; we built it as our own product. It shows where we put the boundaries between layers in an SPA.
03 · How we work
01 · ONE LAYER EACHFetching, caching, session refresh and error handling each have one home in the code. When a session expires, every screen goes through the same refresh path.
02 · CHECKED IN THE BUILDEach of those decisions is enforced by a check in the build, so it still holds in a week when nobody has time to review carefully.
04 · Stack
ReactTypeScriptViteReduxstyled-componentspnpm workspacesESLint rules of our own
Proof
Where we’ve done this before
Case study 01 · Platforms74 / 678Our own design system has three targets: a Vite SPA, Next.js and React Native. The call that renders the login screen is the same, byte for byte, in all of them.Read the case study →Case study 08 · Marketplace506 routesReact and Redux dashboards for five kinds of user on a US marketplace. Each user type got its own branch of the router, /dashboard/{user_type}/{page}, so role checks didn’t spread through the components.Read the case study →Case study 03 · Platforms~50%On the same marketplace, build rules made every API call declare its request and response types and kept each component at 200 lines or fewer.Read the case study →
FAQ
Questions about this service
No. We start with a list of where each feature fetches data, caches it and handles an expired session today. Then we move those pieces into one layer, one at a time.
It is a team convention written as code. The same rule is a warning in the editor and an error in the pre-commit hook and in CI, so it is present at every stage but blocks you only where stopping is cheap.
It depends on the product. Our own design system runs both ways, as a Vite SPA and server-rendered in Next.js, with the same component calls.
Next step
Describe the problem and we’ll come back with three options.
The first call takes 30 minutes, and you’re under no obligation.