Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 6

Connecting Frontend to Flask: A Health Check

Recommended resources

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.

Health Check API Flow Diagram
This diagram illustrates the concept we're implementing: our frontend (client) will query the backend's health endpoint to check its operational status.

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:

  1. Backend Solution (Flask-CORS): We can install and configure the flask-cors library on our backend. This adds specific HTTP headers to the backend's responses (like Access-Control-Allow-Origin), telling the browser that it's safe to allow requests from the frontend's origin.
  2. 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 on localhost: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.

  1. Configure the Vite Proxy:

    • Open frontend/vite.config.js.
    • Modify the file to include the server.proxy configuration. Any request your frontend makes to a path starting with /api will now be forwarded to your Flask server at http://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/health from the frontend and correctly forward it to http://localhost:5000/health. The rewrite part removes the /api prefix before sending it to Flask.

  2. Fetch Health Status in App.jsx:

    • Open frontend/src/App.jsx.
    • Import useState and useEffect from React.
    • Create a state variable to hold the API status (e.g., apiStatus).
    • Use a useEffect hook to fetch data from /api/health.
    • Update the state with the status message from the JSON response.
    • Pass the apiStatus state variable as a prop to your <Header /> component.

    Your App.jsx might 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;
    
  3. Display Status in Header.jsx:

    • Open frontend/src/components/Header.jsx.
    • Modify the component to accept the apiStatus prop.
    • 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;
    
  4. Run and Verify:

    • In your first terminal, navigate to the backend directory, activate your virtual environment, and run flask run. You should see the Flask server running on http://localhost:5000.
    • In your second terminal, navigate to the frontend directory and run npm run dev.
    • Open http://localhost:5173 in your browser. If everything is configured correctly, you should see your dashboard, and the header should display "API Status: ok" with a green dot.

Verification

To confirm that you have successfully connected the frontend and backend, please provide the following:

  1. File Structure: The output of the tree -L 3 frontend/src command (or a similar representation) showing your current frontend project structure.
  2. 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.