stack.menu

React + Vite

An interactive browser app connected to an existing or separate API.

React · Vite · TypeScript · your API

Complete guide (Markdown) · Structured record (JSON)

Original source review: 2026-10-10. Core guidance rechecked: 2026-10-13. Check scope. Dependency combinations and setup need project-specific qualification.

Use cases

Choose it when

Consider another path when

Working practices

Tools by job

browser build and UI: React + Vite + TypeScript

Focused browser development without unnecessary server framework

TypeScript compiles to JS; Vite is tooling, not a backend; keep HTML/CSS competence

validation: Zod at API/client boundaries

Check external values and share explicit contracts

Client checks never replace authoritative backend validation or authorization

Identity ownership: Existing backend owns authentication and authorization

Avoid duplicating external-system ownership in browser code

No database credentials/server secrets in browser; document API/session/CORS contract

Database ownership: Existing backend owns persistence and migrations

Avoid duplicating external-system ownership in browser code

No database credentials/server secrets in browser; document API/session/CORS contract

Background work ownership: Existing backend owns durable jobs

Avoid duplicating external-system ownership in browser code

No database credentials/server secrets in browser; document API/session/CORS contract

Static typing: Strict TypeScript; retain generated project-reference build

Static checks and user-visible browser behavior

Configure router/API failure/session expiry tests; preserve scaffold-specific build scripts

Linting: ESLint

Static checks and user-visible browser behavior

Configure router/API failure/session expiry tests; preserve scaffold-specific build scripts

Domain and component tests: Vitest

Run isolated domain behavior checks with a configured test environment

Install Vitest; preserve Vite plugins or add a separate test configuration. Mock only external boundaries and test failure states.

Browser tests: Playwright

Exercise critical journeys in actual browser engines

Install @playwright/test and matching browsers; configure an isolated test server/data and test session expiry, routing and authorization failures.

deployment: Static asset host chosen by project

Browser build can be independently served

Configure deep-link fallback, API origins, cache invalidation and environment handling; preview is not production

Server state cache: TanStack Query for client-owned remote state

Queries, mutations and invalidation support interactive API screens

Install @tanstack/react-query and provide QueryClient. Define tenant-aware keys, staleTime/retry policy and clear session data on sign-out; in Next prefer server loading until a client cache has a job.

Forms: React Hook Form for complex client forms

Separates client form state and validation from page components

Install react-hook-form only where needed; wire existing runtime schemas deliberately. Render accessible labels/errors; validate and authorize submissions on the server.

Styling: Tailwind CSS when utility styling fits the project

Reusable styling without a runtime component dependency

For Vite install tailwindcss and @tailwindcss/vite, add the plugin and CSS import. Use the framework-specific installation path for Next; retain established styles when present.

Accessible UI primitives: Radix Primitives for complex controls

Provides focus and keyboard behavior for common interaction patterns

Install only used components. Authors still supply names, contrast and meaningful composition; verify keyboard and assistive-technology behavior.

Accessibility checks: axe-core through Playwright + manual keyboard review

Automated audits identify common accessibility defects in real pages

Install @axe-core/playwright; scan representative states and use a screen reader/keyboard. Passing automated rules is not complete accessibility evidence.

Routing: TanStack Router

Typed navigation, route loading and search parameters suit application screens

Install @tanstack/react-router; configure the chosen file-based plugin or code-based routes. Test deep links, not-found routes and browser back; route guards do not replace server authorization.

Live server updates: EventSource for one-way server events

Browser-standard streaming suits status/progress feeds

Backend owns authenticated stream and event IDs. Test reconnect, replay and proxy buffering; EventSource is one-way and its constructor offers no arbitrary authorization-header option. Confirm long-lived connection support on host.

Build with the stack’s strengths

Architecture and developer workflow.

React/Vite builds browser assets. Recommendation: select it when an existing API owns persistence, authorization, email, durable jobs and other privileged effects; choose routing and remote-state tools deliberately. A client-only build has no protected server runtime.

Version scope: Documentation reviewed 11 October 2026: current React docs label 19.3; current Vite docs include migration from v7 and Rolldown build options. Preserve the project's resolved React/Vite/TypeScript/router versions and API schema. SPA guidance is not a claim that Vite supplies SSR or a backend. · Reviewed 2026-10-11

Architecture boundaries

Tools and feedback

Translations to avoid

For an existing application

Keep the contracts while you change the stack.

These are documented options and proposed checks. Inspect the actual source application before adopting a transition.

Browser and installed clients

Inspect the source

Existing URLs, backend API DTOs, errors, permissions and navigation/deep-link semantics.

During coexistence

Recommendation: Replace one route/screen with React while keeping existing API ownership and deep links; contract fixtures cover old/new UI.

Target design

Recommendation: Keep a browser/API split with route loaders or a selected query client; adopt a server framework only when required rendering/backend features justify it.

Rollback

Restore old HTML/assets/routes while API compatibility remains; preserve submitted data and reconcile pending mutations.

Benefits and prerequisites

An independently delivered browser client can evolve behind a stable API.
Requires: Owned routing/hosting fallback and backward-compatible API.
Tradeoffs: A SPA must own routing/data/loading infrastructure; SSR/RSC are additional architecture choices.

Checks before transfer

  • Direct deep links and refresh work from the production host.
  • Old/new clients decode success/error/unknown-field fixtures.
  • Unauthorized direct API requests remain denied.
Identity and authorization

Inspect the source

Backend credential transport, allowed origins, cookies/CSRF, token expiry and account boundaries.

During coexistence

Recommendation: Keep the backend issuer; configure same-origin routing or narrowly allowed credentialed CORS and preserve old clients.

Target design

Recommendation: Centralize credential/error behavior in the API client; enforce authorization and any cookie CSRF protection in the backend.

Rollback

Restore the old browser artifact/origin policy only if existing credential handling remains secure; retain revocation history.

Benefits and prerequisites

One backend authority reduces duplicated browser identity logic.
Requires: Reviewed origin/credential policy and issuer behavior.
Tradeoffs: CORS controls browser response access, not authorization; frontend guards remain presentation only.

Checks before transfer

  • Credentialed requests succeed only for permitted origins.
  • Expired credentials transition to sign-in without endless retries.
  • Cross-tenant and CSRF probes are rejected by the backend.
Caching and shared state

Inspect the source

Current fetch/cache behavior, stale tolerance, retry limits and account-switch isolation.

During coexistence

Recommendation: Introduce query keys for a bounded remote-state category; keep transient form state separate and compare outcomes with the old fetch path.

Target design

Recommendation: Use explicit TanStack Query staleTime, retry, invalidation and account-clear policy where its remote-state cache serves a requirement.

Rollback

Return the category to the old loader and clear the new cache; do not discard durable pending user operations.

Benefits and prerequisites

Shared queries can reuse data and refresh deliberately.
Requires: A QueryClientProvider, stable tenant-aware keys and mutation invalidation.
Tradeoffs: Default stale queries refetch on mount/focus/reconnect; retries can obscure application errors if left unspecified.

Checks before transfer

  • A mutation refreshes affected list/detail views.
  • Switching accounts cannot reuse the old account's records.
  • Network restoration produces one coherent refresh; permission errors do not retry indefinitely.
Realtime transport

Inspect the source

Existing event envelope, authorization, IDs, reconnect behavior and replay/retention rules.

During coexistence

Recommendation: Keep a backend bridge producing the current event contract; move clients by stable subscription cohort rather than arbitrary per-request routing.

Target design

Recommendation: Use EventSource for one-way events when host/credentials fit, WebSocket for bidirectional needs; persist/replay events separately when delivery requires it.

Rollback

Restore old polling/transport using the same cursor domain; reconcile delivered events and keep bridge/history through the rollback window.

Benefits and prerequisites

A standard browser event stream can replace bespoke polling for suitable feeds.
Requires: Authenticated endpoint, event IDs, retention/replay contract and streaming host.
Tradeoffs: EventSource reconnect does not create server event history; its constructor has no arbitrary header option.

Checks before transfer

  • Disconnect after event N and reconnect; no required event is omitted or applied twice.
  • Revocation terminates access and later reconnect is denied.
  • Old/new envelopes decode during mixed-version rollout.
Delivery and recovery

Inspect the source

Existing HTML/CDN/service-worker policy, lazy chunks and open-tab unsaved state.

During coexistence

Recommendation: Keep prior hashed assets and compatible APIs while serving new HTML to a cohort; include any existing service worker's activation/cache rules.

Target design

Recommendation: Revalidate HTML, retain old content-hashed chunks and handle vite:preloadError with a guarded refresh/update flow that preserves drafts.

Rollback

Restore the prior HTML and retained assets, roll service-worker changes through their actual lifecycle, and keep new-client API support.

Benefits and prerequisites

Old tabs can continue loading their release's lazy chunks.
Requires: Asset retention, correct base path and tested update UX.
Tradeoffs: Retention costs storage; refresh may lose state, and reload loops do not fix a wrong CDN policy.

Checks before transfer

  • After deployment an old tab lazy-loads its old route successfully.
  • If a chunk is intentionally unavailable, the update path retains the draft and recovers once.
  • Production HTML/cache headers and API compatibility match the rollout policy.

Read the migration workflow →

Setup

  1. Start in repository parent in a local development workspace with API/session owners identified.
  2. Run npm create vite@latest my-app -- --template react-ts; enter my-app; npm install; record resolved versions and commit lockfile.
  3. Create README with API contract, run/check instructions and environment variable names. Configure strict TypeScript and router/query tooling only as needed.
  4. Add Zod and test tools; configure request validation, error/loading/session-expiry states and authoritative backend authorization tests.
  5. Build to static assets, configure chosen host deep-link behavior and API origins, then run production browser checks.

Verification

Run these in the configured application; they are instructions, not recorded passes.

npm ci
npx tsc --noEmit
npx eslint .
npx vitest run
npm run build
npx playwright test

Open questions

Sources