Proxies

Whenever you're building a full stack application, it's common to run two servers: one for the frontend (like your React or Vite app) and one for the backend (like an Express or Flask API). A proxy is a development tool that helps your frontend talk to your backend as if they were part of the same server.

Why you need proxies in development

Imagine your frontend is a person trying to send a letter to their backend friend across town. Without a proxy, your frontend has to remember the entire address every time. Not fun! With a proxy, it's like dropping the letter at a nearby post office that already knows where to send it.

In development, hardcoding full backend URLs like http://localhost:5000/api/cats everywhere is a maintenance headache. It works locally, but once you deploy your app, those addresses change. You'll have to update every API call manually. A proxy solves this by letting your frontend use shorter, relative paths like fetch('/api/cats'), and the proxy figures out where to actually send the request.

Real world metaphor

Think of a proxy like a hotel front desk. You (the guest/frontend) want to order room service (backend API). Instead of calling the kitchen directly (and needing to know its number), you call the front desk and say "Send me dinner." The front desk (proxy) knows where to forward that request.

When this becomes important

Example scenario

Let’s say you're building a cat rental app. Your backend API runs on http://localhost:5000 and your frontend runs on http://localhost:5173.

Your backend has a route /api/cats. Your frontend should ideally be able to do:

fetch("/api/cats")

But without a proxy, this sends the request to localhost:5173/api/cats — your frontend port, not backend! This fails because the backend lives on port 5000.

Configuring a proxy in Vite

Vite uses a config file located at frontend/vite.config.js. Here’s how you can set up a proxy inside that file:

File location:

frontend/vite.config.js

Code:

import { defineConfig } from "vite";

export default defineConfig(({ mode }) => ({
  server: {
    proxy: {
      "/api": "http://localhost:5000"
    }
  }
}));

This means: whenever your app tries to access a route that starts with /api, Vite will forward the request to http://localhost:5000.

How it works:

Follow-along exercise

Try this hands-on example:

  1. Start your backend on port 5000 with a route at /api/cats
  2. Start your frontend on Vite (usually on port 5173)
  3. In your vite.config.js, add the proxy code above
  4. In a frontend component, use:
    fetch("/api/cats")
      .then(res => res.json())
      .then(data => console.log(data));
  5. Make sure your backend returns JSON data, like [{ name: "Whiskers" }]
  6. Open the browser dev tools and watch the network request get routed correctly!

More things to explore

Extra notes

Always be careful with open proxy setups in production — this tutorial is strictly for development mode. For production, you’ll want to configure a secure reverse proxy or host both frontend and backend under the same domain.

Now go forth and connect those frontend requests to their backend homes with style!