FastAPI and React are a common pairing: a Python backend and a React single-page app in front of it. To make them work as one product you have to sort out five things: how the two communicate, how login works, whether to use one repo or two, how to deploy them, and how to keep your Python models and TypeScript types in sync. This page describes each problem and the setup we use in FastReact.
In development you run two servers. FastAPI runs on port 8000 and Vite serves the React app on
5173. The React app calls the backend over HTTP, so the browser treats every API call as a
cross-origin request, and the backend has to send CORS headers that allow http://localhost:5173. In
production the origins change: the frontend might be on app.example.com and the API on api.example.com, and the CORS
config has to allow that origin instead.
The frontend also needs the API's URL in each environment. In FastReact that is one
environment variable, VITE_API_BASE_URL, read in one fetch wrapper, and the backend reads its allowed origins from config. If you
hardcode either of these it works locally and breaks on your first deploy.
There are two workable options for auth between a SPA and an API: JWTs stored in the browser, or server-side sessions with cookies.
FastReact uses HTTP-only session cookies. FastAPI sets the cookie on login, the browser sends
it on every request (fetch with credentials: 'include'),
and JavaScript cannot read it, so injected scripts cannot steal a token. Sessions are rows in
Postgres, so revoking one server-side is deleting a row. The frontend finds out who is logged
in with a single GET /users/me on load.
What cookies cost you: SameSite has to be set correctly, and if the app and the API are on different subdomains, the cookie domain has to be set so the browser sends it across. That is one-time configuration. FastReact ships with it configured, along with signup, Google OAuth, email verification, password reset, and role-based access. The authentication docs describe the details.
Separate repos for backend and frontend look cleaner, but most features touch both: a new endpoint plus the screen that calls it. With two repos that is two pull requests that have to merge in the right order, and API types that have to be shared between repos somehow.
FastReact uses one repo with backend/ and frontend/ directories. The two
still deploy independently, since they only communicate over HTTP, but a full feature is one commit
and one review.
npm run build turns the React app
into static files, and any static host serves them: Vercel, Netlify, an S3 bucket, nginx. The FastAPI
backend is a regular Python process, so it needs a container platform or a VPS, plus a Postgres
database.
The problems are in the seams: cookies across subdomains, CORS with production origins, and serving the SPA from a sub-path if your setup needs one. The FastReact docs have deployment guides for Railway, Fly.io with Neon and Vercel, DigitalOcean, Azure, and self-hosting on a VPS.
FastAPI generates an OpenAPI spec from your Pydantic models. Orval reads that spec and generates a typed TypeScript client: one typed function per endpoint, with request and response types that match the backend exactly.
That turns API drift into compile errors. Rename a field in a Pydantic model, regenerate the
client (npm run generate in
FastReact), and TypeScript reports every call site that needs updating. Without something like
this, the backend and frontend disagree silently and you find out in production. The setup is
described in the Orval guide.
FastReact is this stack with the decisions above already made, plus the product parts: Stripe subscriptions, teams and roles, an AI copilot with usage billing, transactional email, and an admin dashboard.
Ship production-ready SaaS applications with FastAPI + React. Complete authentication, payments, multi-tenancy, and admin dashboards - deploy anywhere with zero vendor lock-in.
Community
© 2026 FastReact. All rights reserved.
🌼 Made with daisyUIFASTREACT