Serving React build files through FastAPI endpoints - integrating frontend with backend

I’m working on my first web app and trying to figure out how to combine my React frontend with FastAPI backend on one server. Right now I develop them separately but want to serve everything from the same domain.

Currently I use npm start for frontend development and uvicorn main:app --reload for backend testing. When ready to deploy, npm build creates my production files.

I tried this approach but it doesn’t work properly:

@app.get("/", response_class=HTMLResponse)
def homepage():
    return open("../client/build/index.html", "r").read()

This only loads the HTML shell without the React functionality. I think I need to serve the JavaScript bundles and CSS files too, but I’m not sure how.

Two main questions:

  1. What’s the correct way to serve my React build folder from a FastAPI root endpoint?
  2. For different routes like /dashboard, /profile, /settings - do I need separate React projects or can one React app handle multiple pages?

I want to avoid CORS issues by keeping everything on one server. Any guidance on the proper setup would be helpful.

u can use StaticFiles from fastapi.staticfiles to serve your build folder. try app.mount("/static", StaticFiles(directory="../client/build/static"), name="static") then serve index.html for all routes and let React Router manage the routing. it works great for SPAs!

The Problem:

You’re trying to serve a React frontend built with npm build from a FastAPI backend, but the React functionality isn’t working. Your current approach only loads the HTML shell. You also want to understand how to handle multiple routes within your React app and avoid CORS issues by keeping everything on one server.

:gear: Step-by-Step Guide:

  1. Mount the entire build directory using StaticFiles: This is the core solution. FastAPI needs to serve not just your index.html but all the associated static assets (JavaScript bundles, CSS, images, etc.) generated by npm build. Use the StaticFiles middleware and the app.mount() method to correctly serve your entire build directory:
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles

app = FastAPI()
app.mount("/", StaticFiles(directory="../client/build", html=True), name="static")

# ... your FastAPI API routes ...

The html=True argument is crucial. It instructs FastAPI to serve index.html as a fallback when a requested path doesn’t directly match a static file. This ensures that any route not explicitly defined in your FastAPI backend will be handled by React Router.

  1. Verify your ../client/build directory: Double-check that the path ../client/build is correct relative to your FastAPI application’s location. The npm build command should have created this directory with your production-ready React files. Make sure that your index.html is properly located within the directory. If you are using a different build output directory, adjust the path accordingly.

  2. Ensure your React Router configuration is correct: React Router handles client-side routing within your single-page application. Make sure your React app is properly configured to handle different routes like /dashboard, /profile, and /settings. These routes should be defined and managed entirely within your React code. Use your browser’s developer tools to inspect the network requests and ensure that the correct JavaScript bundles and other assets are being loaded.

  3. Placement of API routes: The app.mount("/", ...) call should come before defining your FastAPI API routes. This ensures that requests for static files are handled by StaticFiles before reaching your API routes. Incorrect ordering can lead to your API routes intercepting requests for static assets.

:thinking: Understanding the “Why” (The Root Cause):

The initial approach of only serving index.html failed because React applications rely on JavaScript bundles and other static assets to function. Serving only the index.html file provides the basic HTML structure but lacks the necessary JavaScript code to make the application interactive. By mounting the entire build directory, FastAPI provides the static files that React needs. The html=True parameter ensures the root index.html is correctly served for all routes handled by React Router. This combined approach avoids unnecessary complexity and keeps everything neatly organized on a single server, thus avoiding CORS issues.

:mag: Common Pitfalls & What to Check Next:

  • Incorrect build directory path: Double-check the path ../client/build in your FastAPI code. A slight typo can prevent the files from being served correctly.
  • Incorrect npm build command: Make sure you’re using the correct command (npm build) and that your build process is generating the expected files in the build directory. Verify the output of your npm build command to confirm the expected directory structure. If using a different build tool like webpack, adjust accordingly.
  • React Router issues: If your pages still don’t load correctly, carefully review your React Router setup. Ensure that your routes are defined correctly, and that React Router is working as expected. Use your browser’s developer tools (network tab) to inspect which assets are being requested and whether they are loaded successfully.
  • File Permissions: Ensure the webserver user has read permissions for the entire ../client/build directory and its contents.

:speech_balloon: Still running into issues? Share your (sanitized) config files, the exact command you ran, and any other relevant details. The community is here to help!

yea, it seems u need to serve your static files too! fastapi can do that easily. just mount your build directory as static files. and about routes, u can def handle them with one react app using react router! have u tried that yet?