{
  "id": "typescript-react-vite-browser",
  "name": "TypeScript browser application with an existing API",
  "use_cases": [
    "Interactive dashboards",
    "API-backed browser tools",
    "Client-rendered applications"
  ],
  "choose_when": [
    "Backend/identity already have owners",
    "SSR is not a product requirement",
    "Browser UI and API can be deployed independently"
  ],
  "avoid_when": [
    "Searchable server-rendered content is central",
    "The task requires native device UI",
    "Team expects the frontend scaffold to supply backend auth or persistence"
  ],
  "tools": [
    {
      "job": "browser build and UI",
      "default": "React + Vite + TypeScript",
      "alternatives": [
        "Next.js for full-stack/SSR",
        "TanStack Start when routing/server integration is needed"
      ],
      "reason": "Focused browser development without unnecessary server framework",
      "limits": "TypeScript compiles to JS; Vite is tooling, not a backend; keep HTML/CSS competence",
      "source_urls": [
        "https://vite.dev/guide/",
        "https://tanstack.com/start/latest",
        "https://react.dev/learn/typescript"
      ]
    },
    {
      "job": "validation",
      "default": "Zod at API/client boundaries",
      "alternatives": [
        "Use the existing API's schema/code generation"
      ],
      "reason": "Check external values and share explicit contracts",
      "limits": "Client checks never replace authoritative backend validation or authorization",
      "source_urls": [
        "https://zod.dev/"
      ]
    },
    {
      "job": "Identity ownership",
      "default": "Existing backend owns authentication and authorization",
      "alternatives": [
        "Adopt full-stack Node record when backend is in scope"
      ],
      "reason": "Avoid duplicating external-system ownership in browser code",
      "limits": "No database credentials/server secrets in browser; document API/session/CORS contract",
      "source_urls": [
        "https://nextjs.org/docs/app/guides/authentication"
      ]
    },
    {
      "job": "Database ownership",
      "default": "Existing backend owns persistence and migrations",
      "alternatives": [
        "Adopt full-stack Node record when backend is in scope"
      ],
      "reason": "Avoid duplicating external-system ownership in browser code",
      "limits": "No database credentials/server secrets in browser; document API/session/CORS contract",
      "source_urls": [
        "https://nextjs.org/docs/app/guides/authentication"
      ]
    },
    {
      "job": "Background work ownership",
      "default": "Existing backend owns durable jobs",
      "alternatives": [
        "Adopt full-stack Node record when backend is in scope"
      ],
      "reason": "Avoid duplicating external-system ownership in browser code",
      "limits": "No database credentials/server secrets in browser; document API/session/CORS contract",
      "source_urls": [
        "https://nextjs.org/docs/app/guides/authentication"
      ]
    },
    {
      "job": "Static typing",
      "default": "Strict TypeScript; retain generated project-reference build",
      "alternatives": [
        "Preserve existing compatible tooling"
      ],
      "reason": "Static checks and user-visible browser behavior",
      "limits": "Configure router/API failure/session expiry tests; preserve scaffold-specific build scripts",
      "source_urls": [
        "https://vite.dev/guide/",
        "https://nextjs.org/docs/app/guides/testing/vitest",
        "https://nextjs.org/docs/app/guides/testing/playwright"
      ]
    },
    {
      "job": "Linting",
      "default": "ESLint",
      "alternatives": [
        "Preserve existing compatible tooling"
      ],
      "reason": "Static checks and user-visible browser behavior",
      "limits": "Configure router/API failure/session expiry tests; preserve scaffold-specific build scripts",
      "source_urls": [
        "https://vite.dev/guide/",
        "https://nextjs.org/docs/app/guides/testing/vitest",
        "https://nextjs.org/docs/app/guides/testing/playwright"
      ]
    },
    {
      "job": "Domain and component tests",
      "default": "Vitest",
      "alternatives": [
        "Preserve existing compatible tooling"
      ],
      "reason": "Run isolated domain behavior checks with a configured test environment",
      "limits": "Install Vitest; preserve Vite plugins or add a separate test configuration. Mock only external boundaries and test failure states.",
      "source_urls": [
        "https://vitest.dev/guide/"
      ]
    },
    {
      "job": "Browser tests",
      "default": "Playwright",
      "alternatives": [
        "Preserve existing compatible tooling"
      ],
      "reason": "Exercise critical journeys in actual browser engines",
      "limits": "Install @playwright/test and matching browsers; configure an isolated test server/data and test session expiry, routing and authorization failures.",
      "source_urls": [
        "https://playwright.dev/docs/intro"
      ]
    },
    {
      "job": "deployment",
      "default": "Static asset host chosen by project",
      "alternatives": [
        "Server-rendered framework when justified"
      ],
      "reason": "Browser build can be independently served",
      "limits": "Configure deep-link fallback, API origins, cache invalidation and environment handling; preview is not production",
      "source_urls": [
        "https://vite.dev/guide/"
      ]
    },
    {
      "job": "Server state cache",
      "default": "TanStack Query for client-owned remote state",
      "alternatives": [
        "Next server loading for server-owned data",
        "Router loaders for simple route data"
      ],
      "reason": "Queries, mutations and invalidation support interactive API screens",
      "limits": "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.",
      "source_urls": [
        "https://tanstack.com/query/latest/docs/framework/react/guides/important-defaults"
      ]
    },
    {
      "job": "Forms",
      "default": "React Hook Form for complex client forms",
      "alternatives": [
        "Native HTML forms for simple submissions"
      ],
      "reason": "Separates client form state and validation from page components",
      "limits": "Install react-hook-form only where needed; wire existing runtime schemas deliberately. Render accessible labels/errors; validate and authorize submissions on the server.",
      "source_urls": [
        "https://github.com/react-hook-form/react-hook-form"
      ]
    },
    {
      "job": "Styling",
      "default": "Tailwind CSS when utility styling fits the project",
      "alternatives": [
        "CSS Modules or existing CSS design system"
      ],
      "reason": "Reusable styling without a runtime component dependency",
      "limits": "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.",
      "source_urls": [
        "https://tailwindcss.com/docs/installation/using-vite"
      ]
    },
    {
      "job": "Accessible UI primitives",
      "default": "Radix Primitives for complex controls",
      "alternatives": [
        "Semantic native HTML controls"
      ],
      "reason": "Provides focus and keyboard behavior for common interaction patterns",
      "limits": "Install only used components. Authors still supply names, contrast and meaningful composition; verify keyboard and assistive-technology behavior.",
      "source_urls": [
        "https://www.radix-ui.com/primitives/docs/overview/accessibility"
      ]
    },
    {
      "job": "Accessibility checks",
      "default": "axe-core through Playwright + manual keyboard review",
      "alternatives": [
        "Preserve an existing compatible project choice"
      ],
      "reason": "Automated audits identify common accessibility defects in real pages",
      "limits": "Install @axe-core/playwright; scan representative states and use a screen reader/keyboard. Passing automated rules is not complete accessibility evidence.",
      "source_urls": [
        "https://playwright.dev/docs/accessibility-testing"
      ]
    },
    {
      "job": "Routing",
      "default": "TanStack Router",
      "alternatives": [
        "React Router in established projects",
        "No router for a single screen"
      ],
      "reason": "Typed navigation, route loading and search parameters suit application screens",
      "limits": "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.",
      "source_urls": [
        "https://tanstack.com/router/latest/docs/overview"
      ]
    },
    {
      "job": "Live server updates",
      "default": "EventSource for one-way server events",
      "alternatives": [
        "WebSocket service for bidirectional collaboration",
        "Polling for infrequent updates"
      ],
      "reason": "Browser-standard streaming suits status/progress feeds",
      "limits": "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.",
      "source_urls": [
        "https://html.spec.whatwg.org/multipage/server-sent-events.html"
      ]
    }
  ],
  "setup_steps": [
    "Start in repository parent in a local development workspace with API/session owners identified.",
    "Run npm create vite@latest my-app -- --template react-ts; enter my-app; npm install; record resolved versions and commit lockfile.",
    "Create README with API contract, run/check instructions and environment variable names. Configure strict TypeScript and router/query tooling only as needed.",
    "Add Zod and test tools; configure request validation, error/loading/session-expiry states and authoritative backend authorization tests.",
    "Build to static assets, configure chosen host deep-link behavior and API origins, then run production browser checks."
  ],
  "verification_commands": [
    "npm ci",
    "npx tsc --noEmit",
    "npx eslint .",
    "npx vitest run",
    "npm run build",
    "npx playwright test"
  ],
  "evidence_status": "documentation-reviewed",
  "sources": [
    {
      "url": "https://vite.dev/guide/",
      "title": "Vite getting started",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://tanstack.com/start/latest",
      "title": "TanStack Start",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://zod.dev/",
      "title": "Zod",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://nextjs.org/docs/app/guides/authentication",
      "title": "Next.js authentication",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://nextjs.org/docs/app/guides/testing/vitest",
      "title": "Next.js Vitest",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://nextjs.org/docs/app/guides/testing/playwright",
      "title": "Next.js Playwright",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://react.dev/learn/typescript",
      "title": "React TypeScript",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://tanstack.com/query/latest/docs/framework/react/guides/important-defaults",
      "title": "TanStack Query important defaults",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://github.com/react-hook-form/react-hook-form",
      "title": "React Hook Form repository",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://tailwindcss.com/docs/installation/using-vite",
      "title": "Tailwind Vite installation",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://www.radix-ui.com/primitives/docs/overview/accessibility",
      "title": "Radix accessibility",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://playwright.dev/docs/accessibility-testing",
      "title": "Playwright accessibility testing",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://tanstack.com/router/latest/docs/overview",
      "title": "TanStack Router overview",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://html.spec.whatwg.org/multipage/server-sent-events.html",
      "title": "HTML EventSource standard",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://vitest.dev/guide/",
      "title": "Vitest guide",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://playwright.dev/docs/intro",
      "title": "Playwright installation",
      "checked_date": "2026-10-13"
    }
  ],
  "open_questions": [
    "Which API and identity owner defines schemas, cookies/tokens and CORS?",
    "Do routes need shareable URLs, offline behavior or server rendering?",
    "Which browser/device matrix and accessibility requirements must be met?",
    "Which static host supports route fallbacks and the selected API origins?"
  ],
  "title": "React + Vite",
  "language": "TypeScript",
  "group": "Web applications",
  "kind": [
    "web"
  ],
  "ui": "client",
  "host": "static",
  "summary": "An interactive browser app connected to an existing or separate API.",
  "shape": "React · Vite · TypeScript · your API",
  "tradeoff": "This is a frontend. Your backend still owns identity, data permissions and durable work.",
  "research_file": "typescript.json",
  "reviewed": "2026-10-10",
  "best_practices": [
    "Keep credentials, SQL access and authorization behind the API. Browser validation does not establish permission.",
    "Keep strict TypeScript and validate API responses where data crosses trust boundaries.",
    "Choose a router and server-state cache only when navigation and data complexity need them.",
    "Test production asset paths and direct navigation to nested routes. Offline use needs explicit storage, synchronization and conflict rules."
  ],
  "research_freshness": {
    "core_guidance_checked_on": "2026-10-13",
    "sources": [
      "https://vite.dev/guide/",
      "https://react.dev/learn/typescript"
    ],
    "scope": "Core framework roles, current setup/agent documentation and cited-source availability rechecked; not a reimplementation or exhaustive semantic audit of every third-party dependency."
  },
  "guide_url": "/stacks/typescript-react-vite-browser/",
  "markdown_url": "/stacks/typescript-react-vite-browser/guide.md",
  "json_url": "/stacks/typescript-react-vite-browser/record.json",
  "architecture_and_migration": {
    "id": "typescript-react-vite-browser",
    "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.",
    "operating_model": "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.",
    "architecture": [
      "Views consume route-loaded or query-cached DTOs; one API client module defines credentials, errors, cancellation and runtime validation. Backend ownership remains independent of UI language.",
      "Recommendation: domain state stays on the server; transient form/navigation state stays in the browser. Use tenant-aware cache keys and an explicit account-switch/reset policy.",
      "Bundled VITE_ values are public configuration. Keep database, provider and signing credentials in the backend; a development proxy is only local routing.",
      "Recommendation: retain content-hashed old chunks during rollout, revalidate HTML and provide a guarded update path for stale tabs. Add service-worker storage/adoption policy only if offline operation is required."
    ],
    "developer_workflow": [
      "Start at the source README, API schema and lockfile. For a new local prototype npm create vite@latest my-app -- --template react-ts creates a starter; record resolved versions before promoting it. Existing applications keep their package manager.",
      "Use npm ci, the configured TypeScript project check (for the standard scaffold npx tsc -b) and npm run build. npm run dev is local development; npm run preview previews a build and is not the production host.",
      "Configure routing, typed API boundaries, TanStack Query only where useful and its QueryClientProvider. Define loading, stale, denied and offline states before using retries.",
      "Recommendation: use browser network/debug tooling and React profiling for the actual slow interaction. Configure Playwright with old/new API fixtures; run npx playwright test only after installing its runner/browsers and setting an isolated webServer."
    ],
    "avoid": [
      "Bundling a secret as VITE_API_KEY publishes it to users; moving its string into a frontend module does not create a trust boundary.",
      "Rebuilding server authorization as React route guards allows direct unauthorized API calls.",
      "Independent fetching in nested effects creates waterfalls and duplicated state ownership; use route loaders or a selected remote-state cache where appropriate.",
      "Treating TanStack Query defaults as an application freshness contract overlooks refetch/retry behavior and account boundaries.",
      "Deleting old chunks on deployment breaks lazy imports in open tabs; repeated automatic reload can also discard unsaved work."
    ],
    "transitions": [
      {
        "capability": "client",
        "existing_contract": "Existing URLs, backend API DTOs, errors, permissions and navigation/deep-link semantics.",
        "coexistence": "Recommendation: Replace one route/screen with React while keeping existing API ownership and deep links; contract fixtures cover old/new UI.",
        "target": "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.",
        "benefits": [
          {
            "benefit": "An independently delivered browser client can evolve behind a stable API.",
            "prerequisites": "Owned routing/hosting fallback and backward-compatible API.",
            "tradeoffs": "A SPA must own routing/data/loading infrastructure; SSR/RSC are additional architecture choices."
          }
        ],
        "checks": [
          "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."
        ],
        "rollback": "Restore old HTML/assets/routes while API compatibility remains; preserve submitted data and reconcile pending mutations.",
        "sources": [
          "https://react.dev/learn/build-a-react-app-from-scratch",
          "https://vite.dev/guide/static-deploy"
        ],
        "id": "client-1"
      },
      {
        "capability": "identity",
        "existing_contract": "Backend credential transport, allowed origins, cookies/CSRF, token expiry and account boundaries.",
        "coexistence": "Recommendation: Keep the backend issuer; configure same-origin routing or narrowly allowed credentialed CORS and preserve old clients.",
        "target": "Recommendation: Centralize credential/error behavior in the API client; enforce authorization and any cookie CSRF protection in the backend.",
        "benefits": [
          {
            "benefit": "One backend authority reduces duplicated browser identity logic.",
            "prerequisites": "Reviewed origin/credential policy and issuer behavior.",
            "tradeoffs": "CORS controls browser response access, not authorization; frontend guards remain presentation only."
          }
        ],
        "checks": [
          "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."
        ],
        "rollback": "Restore the old browser artifact/origin policy only if existing credential handling remains secure; retain revocation history.",
        "sources": [
          "https://fetch.spec.whatwg.org/",
          "https://vite.dev/guide/env-and-mode"
        ],
        "id": "identity-1"
      },
      {
        "capability": "cache",
        "existing_contract": "Current fetch/cache behavior, stale tolerance, retry limits and account-switch isolation.",
        "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": "Recommendation: Use explicit TanStack Query staleTime, retry, invalidation and account-clear policy where its remote-state cache serves a requirement.",
        "benefits": [
          {
            "benefit": "Shared queries can reuse data and refresh deliberately.",
            "prerequisites": "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": [
          "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."
        ],
        "rollback": "Return the category to the old loader and clear the new cache; do not discard durable pending user operations.",
        "sources": [
          "https://tanstack.com/query/latest/docs/framework/react/guides/important-defaults"
        ],
        "id": "cache-1"
      },
      {
        "capability": "realtime",
        "existing_contract": "Existing event envelope, authorization, IDs, reconnect behavior and replay/retention rules.",
        "coexistence": "Recommendation: Keep a backend bridge producing the current event contract; move clients by stable subscription cohort rather than arbitrary per-request routing.",
        "target": "Recommendation: Use EventSource for one-way events when host/credentials fit, WebSocket for bidirectional needs; persist/replay events separately when delivery requires it.",
        "benefits": [
          {
            "benefit": "A standard browser event stream can replace bespoke polling for suitable feeds.",
            "prerequisites": "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": [
          "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."
        ],
        "rollback": "Restore old polling/transport using the same cursor domain; reconcile delivered events and keep bridge/history through the rollback window.",
        "sources": [
          "https://html.spec.whatwg.org/multipage/server-sent-events.html"
        ],
        "id": "realtime-1"
      },
      {
        "capability": "operations",
        "existing_contract": "Existing HTML/CDN/service-worker policy, lazy chunks and open-tab unsaved state.",
        "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": "Recommendation: Revalidate HTML, retain old content-hashed chunks and handle vite:preloadError with a guarded refresh/update flow that preserves drafts.",
        "benefits": [
          {
            "benefit": "Old tabs can continue loading their release's lazy chunks.",
            "prerequisites": "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": [
          "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."
        ],
        "rollback": "Restore the prior HTML and retained assets, roll service-worker changes through their actual lifecycle, and keep new-client API support.",
        "sources": [
          "https://vite.dev/guide/build",
          "https://vite.dev/guide/static-deploy"
        ],
        "id": "operations-1"
      }
    ],
    "sources": [
      {
        "url": "https://react.dev/learn/build-a-react-app-from-scratch",
        "title": "React Build an app from Scratch",
        "claim": "A Vite client-only starter requires deliberate routing/data tools; SSR/RSC are additional architecture work."
      },
      {
        "url": "https://vite.dev/guide/",
        "title": "Vite Getting Started",
        "claim": "Scaffold command and runtime requirements must be checked against resolved Vite version."
      },
      {
        "url": "https://vite.dev/guide/env-and-mode",
        "title": "Vite Environment Variables and Modes",
        "claim": "VITE_ values are bundled into client code and must not contain secrets."
      },
      {
        "url": "https://vite.dev/guide/build",
        "title": "Vite Building for Production",
        "claim": "Deleted old chunks can fail dynamic imports; vite:preloadError and HTML cache policy support recovery design."
      },
      {
        "url": "https://vite.dev/guide/static-deploy",
        "title": "Vite Deploying a Static Site",
        "claim": "Build output needs a chosen production host; vite preview is for local preview."
      },
      {
        "url": "https://tanstack.com/query/latest/docs/framework/react/guides/important-defaults",
        "title": "TanStack Query Important Defaults",
        "claim": "Staleness, mount/focus/reconnect refetch, garbage collection and retries require explicit application choices."
      },
      {
        "url": "https://fetch.spec.whatwg.org/",
        "title": "WHATWG Fetch Standard",
        "claim": "Cross-origin response sharing and credential handling are browser protocol rules, separate from application authorization."
      },
      {
        "url": "https://html.spec.whatwg.org/multipage/server-sent-events.html",
        "title": "WHATWG Server-sent Events",
        "claim": "EventSource provides reconnect and event IDs; constructor options include withCredentials, not arbitrary headers."
      }
    ],
    "reviewed_at": "2026-10-11",
    "evidence": "documentation-reviewed"
  },
  "rewrite_url": "/rewrite/guide.md",
  "migration_contracts_url": "/rewrite/contracts.json",
  "agent_workflow": [
    "Read README, dependency manifests, lockfiles, runtime pins and the maintained project workflow before changing anything. Preserve an existing stack unless reconsidering it is part of the request.",
    "Use this guide to select tools by requirement. Resolve compatible versions from official and installed-version documentation; record the actual lockfile and runtime versions.",
    "Create a plan for schema changes, identity, authorization, external effects and deployment. A library choice does not complete its integration.",
    "Run relevant checks after configuration. Exercise the real interface, failure paths and packaged artifact on the intended target. Report commands, versions, results and untested behavior.",
    "On failure, retain the command and diagnostic, fix the failing prerequisite and resume there. Do not regenerate over existing work or suppress failures to make a check green."
  ],
  "selection": {
    "native_ui": false,
    "static_hosting": true,
    "offline_client_candidate": true
  },
  "coverage_note": "Tools are curated starting points for this application role. Exact versions, integrations and offline behavior require project-specific qualification."
}
