CalcSnippets Search
Web 3 min read

Vite Proxy Config for Local API Dev: Stop Fighting CORS in Frontend Development

A practical Vite proxy guide that shows how to route local frontend requests to a backend, avoid repetitive CORS setup, and fix the proxy mistakes that make local development noisier than it needs to be.

Why this problem wastes so much time: frontend developers often treat CORS errors as a normal part of local development when the cleaner fix is often to stop making the browser cross origins in the first place.

The local development problem

Your frontend might be running here:

http://localhost:5173

Your backend might be running here:

http://localhost:8000

If the browser calls the backend directly, you are now crossing origins. That means CORS enters the picture. Sometimes that is fine. Often it is just noise while you are building UI.

Why a Vite proxy is useful

Instead of making the browser hit http://localhost:8000/api, you can make the browser call /api on the Vite dev server and let Vite proxy it to the backend.

That means the browser thinks it is still talking to the same origin:

http://localhost:5173/api

This simplifies frontend work and reduces the number of “why is preflight failing?” detours.

A simple vite.config.ts proxy

import { defineConfig } from "vite";

export default defineConfig({
  server: {
    proxy: {
      "/api": {
        target: "http://localhost:8000",
        changeOrigin: true,
      },
    },
  },
});

With that in place, a frontend request like this:

fetch("/api/users")

gets forwarded to:

http://localhost:8000/api/users

When path rewriting is needed

Sometimes the backend does not expose /api. Maybe it expects /users directly. In that case:

import { defineConfig } from "vite";

export default defineConfig({
  server: {
    proxy: {
      "/api": {
        target: "http://localhost:8000",
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, ""),
      },
    },
  },
});

Now /api/users becomes /users on the upstream server.

Why developers think the proxy is broken

Usually one of these is happening:

  1. they forgot to restart Vite after editing config
  2. the frontend is still using a hard-coded backend URL
  3. the proxy path does not match the request path
  4. the backend itself is failing, so the proxy just forwards an error

That last point matters. The proxy does not make a broken API healthy. It only changes the route between browser and backend.

A cleaner frontend pattern

Do not scatter absolute local URLs across the app:

fetch("http://localhost:8000/api/users")

Prefer a relative path in development:

fetch("/api/users")

That makes the frontend more portable, and it keeps the local setup closer to how a reverse proxy often works in real deployments.

When you still need real CORS

If your production architecture truly serves frontend and backend from different origins, then yes, backend CORS still matters. The Vite proxy is not a replacement for production security policy. It is a development convenience.

That distinction matters. Proxying during local development keeps the browser calm. Production still needs correct backend behavior.

Final recommendation

If your local frontend is repeatedly tripping over CORS, first ask whether the browser needs to cross origins at all. In many Vite setups, the cleanest answer is no. A small proxy config removes a lot of noise and lets you debug the actual product instead of the transport layer.

That is the real win. The proxy is not clever. It is just disciplined. It cuts out one entire class of local-development friction so the frontend and backend can move faster without inventing unnecessary security theater during UI work.

Sources

Keep reading

Related guides