Hello! In our previous lesson, you successfully built a frontend skeleton for our recommendation dashboard using React and Tailwind CSS. You now have a visually appealing, component-based static interface running locally. On the other side, our Flask backend is also ready, complete with a /health endpoint.
This lesson is about bridging the gap between these two independent services. Our goal is to establish basic communication between the frontend and the Flask backend, allowing the frontend to call the /health endpoint. We'll make our React app fetch the status from our Flask API and display it, confirming they can talk to each other. This is a foundational step for building any full-stack application.

1. The Cross-Origin Challenge (CORS)
Before we write any code, we need to understand a browser security feature called Cross-Origin Resource Sharing (CORS). By default, browsers block web pages from making API requests to a server at a different "origin" (protocol, domain, or port).
Our setup is a classic example:
- React Frontend (Vite dev server):
http://localhost:5173 - Flask Backend:
http://localhost:5000
Since the ports are different, they are considered different origins. If our React app tries to fetch data from Flask, the browser will block the request.
We have two primary ways to solve this:
- Backend Solution (Flask-CORS): We can install and configure the
flask-corslibrary on our backend. This adds specific HTTP headers to the backend's responses (likeAccess-Control-Allow-Origin), telling the browser that it's safe to allow requests from the frontend's origin. - Frontend Solution (Proxy): During development, we can configure our Vite development server to act as a proxy. When the React app makes an API request to its own server (e.g., to
/api/health), Vite intercepts it and forwards it to the Flask backend onlocalhost:5000. From the browser's perspective, no cross-origin request ever happened.
For development, the proxy method is often cleaner and simpler. We will use that approach. The article from Miguel Grinberg provides an excellent, modern guide on this exact setup.
Create a React + Flask Project in 2025 - miguelgrinberg.com
This article, 'Create a React + Flask Project in 2025', explains how to connect a Vite-based React frontend to a Flask backend, including the crucial proxy configuration.
Read the section titled 'Creating the Flask Back End', focusing on the part that starts with 'To configure the API request forwarding Vite provides a proxy server option.' Pay close attention to the modification of the vite.config.js file. This is exactly what we need to do.
2. Making the API Call in React
With the proxy configured, we can now make a fetch request from our React application. The standard place to perform such an action is within the useEffect hook, ensuring the data is fetched when the component first mounts.
We will fetch the data in our main App.jsx component and then pass the result down to the Header.jsx component to be displayed. This keeps our data-fetching logic at a higher level.
The video below demonstrates this useEffect and useState pattern clearly. Although it uses a slightly different setup (create-react-app), the core React logic for fetching and managing state is identical.
How to Create a Flask + React Project | Python Backend + React Frontend
This video, 'How to Create a Flask + React Project', shows the fundamental pattern of using useEffect to fetch data from a backend API and useState to store and display it.
Watch the segment from 05:41 to 09:03. Focus on how useState is used to create a state variable and useEffect is used with fetch to populate that variable with data from the backend when the component loads. We will adapt this pattern for our /health endpoint.
Your Task: Connect Frontend to Backend
It's time to connect the two halves of our application. You will need to have two terminal windows open for this task: one for the frontend and one for the backend.
-
Configure the Vite Proxy:
- Open
frontend/vite.config.js. - Modify the file to include the
server.proxyconfiguration. Any request your frontend makes to a path starting with/apiwill now be forwarded to your Flask server athttp://localhost:5000.
// frontend/vite.config.js import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' // https://vitejs.dev/config/ export default defineConfig({ plugins: [react()], server: { proxy: { '/api': { target: 'http://localhost:5000', changeOrigin: true, rewrite: (path) => path.replace(/^\/api/, ''), }, } } })Note: In your Flask backend, the endpoint is
/health. The proxy configuration above will take a request to/api/healthfrom the frontend and correctly forward it tohttp://localhost:5000/health. Therewritepart removes the/apiprefix before sending it to Flask. - Open
-
Fetch Health Status in
App.jsx:- Open
frontend/src/App.jsx. - Import
useStateanduseEffectfrom React. - Create a state variable to hold the API status (e.g.,
apiStatus). - Use a
useEffecthook tofetchdata from/api/health. - Update the state with the
statusmessage from the JSON response. - Pass the
apiStatusstate variable as a prop to your<Header />component.
Your
App.jsxmight look something like this after modification:// frontend/src/App.jsx import { useState, useEffect } from 'react'; import Header from './components/Header'; import Sidebar from './components/Sidebar'; import ProductCard from './components/ProductCard'; function App() { const [apiStatus, setApiStatus] = useState('Checking...'); useEffect(() => { fetch('/api/health') .then(res => res.json()) .then(data => { setApiStatus(data.status); }) .catch(err => { console.error(err); setApiStatus('Error'); }); }, []); // Empty dependency array ensures this runs only once on mount // Your existing product data and JSX const products = [ { name: 'Stylish Shirt', price: '49.99', imageUrl: 'https://via.placeholder.com/150' }, // ... other products ]; return ( <div className="flex h-screen bg-gray-100"> <Sidebar /> <div className="flex-1 flex flex-col overflow-hidden"> <Header apiStatus={apiStatus} /> <main className="flex-1 overflow-x-hidden overflow-y-auto bg-gray-200"> <div className="container mx-auto px-6 py-8"> <h3 className="text-gray-700 text-3xl font-medium">Our Top Picks for You</h3> {/* Your product grid */} </div> </main> </div> </div> ); } export default App; - Open
-
Display Status in
Header.jsx:- Open
frontend/src/components/Header.jsx. - Modify the component to accept the
apiStatusprop. - Display the status. For a better user experience, you can add a small colored dot to indicate the status visually (e.g., green for "ok", red for "error").
Here is an example of how you could modify
Header.jsx:// frontend/src/components/Header.jsx import React from 'react'; const Header = ({ apiStatus }) => { const isOk = apiStatus === 'ok'; return ( <header className="flex justify-between items-center p-4 bg-white border-b-2"> <h1 className="text-xl font-semibold">H&M Recommendation Dashboard</h1> <div className="flex items-center"> <span className="mr-2 text-sm text-gray-600">API Status:</span> <span className={`h-3 w-3 rounded-full ${isOk ? 'bg-green-500' : 'bg-red-500'}`}></span> <span className="ml-2 text-sm font-semibold">{apiStatus}</span> </div> </header> ); }; export default Header; - Open
-
Run and Verify:
- In your first terminal, navigate to the
backenddirectory, activate your virtual environment, and runflask run. You should see the Flask server running onhttp://localhost:5000. - In your second terminal, navigate to the
frontenddirectory and runnpm run dev. - Open
http://localhost:5173in your browser. If everything is configured correctly, you should see your dashboard, and the header should display "API Status: ok" with a green dot.
- In your first terminal, navigate to the
Verification
To confirm that you have successfully connected the frontend and backend, please provide the following:
- File Structure: The output of the
tree -L 3 frontend/srccommand (or a similar representation) showing your current frontend project structure. - Screenshot URL: Take a screenshot of your running application, showing the dashboard with the "API Status: ok" message in the header. Upload it to a service like Imgur and provide the direct image link.
Excellent work! You've just achieved a major milestone in full-stack development by making two separate services communicate. This client-server architecture is the backbone of our application.
In the next lesson, we will leave the application scaffolding behind and dive into the core of our project: Exploratory Feature Engineering. We'll start processing our raw data to extract the first meaningful features for our recommendation model.