Vite Proxy Folder Name Conflict

SkillWeb & browsing

Fix 404 errors for frontend JS files when using Vite proxy. Use when: (1) Browser shows "Failed to load resource: 404" for JS/JSX files that exist on disk, (2) Vite serves HTML instead of JavaScript for module imports, (3) You have a client folder named "api" (or similar) AND a Vite proxy configured for "/api". The proxy intercepts requests for client-side files when folder names match proxy paths. Applies to Vite, Vite+React, Vite+Vue projects with dev server proxy configuration.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Vite Proxy Folder Name Conflict skill

What this skill tells your AI

The instructions your AI receives, as published by divinevideo/divine-mobile in .agents/skills/vite-proxy-folder-name-conflict/SKILL.md and read by ahel’s review.

Problem

Frontend JavaScript/JSX files return 404 errors even though they exist on disk. The browser console shows errors like:

usePeople.js:1 Failed to load resource: the server responded with a status of 404 (Not Found)
useMedia.js:1 Failed to load resource: the server responded with a status of 404 (Not Found)

The files exist at paths like src/client/api/hooks/usePeople.js, but Vite returns 404 or serves HTML instead of JavaScript.

Context / Trigger Conditions

This issue occurs when ALL of these conditions are true:

  1. Vite dev server with proxy configuration in vite.config.js:

    server: {
      proxy: {
        '/api': {
          target: 'http://localhost:3001',
          changeOrigin: true,
        },
      },
    }
    
  2. Client-side folder with the same name as the proxy path:

    src/client/
    ├── api/           ← Folder name matches proxy path "/api"
    │   ├── client.js
    │   └── hooks/
    │       ├── usePeople.js
    │       └── useMedia.js
    
  3. Imports that resolve to the proxied path:

    // In src/client/pages/Directory.jsx
    import { usePeople } from '../api/hooks/usePeople.js';
    // Vite transforms this to: /api/hooks/usePeople.js
    // This matches the proxy rule and gets sent to backend!
    

Root Cause

Vite's module resolution transforms relative imports to absolute paths. When you import ../api/hooks/usePeople.js from a page, Vite resolves it to /api/hooks/usePeople.js.

The proxy configuration matches paths starting with /api and forwards them to the backend server. Since /api/hooks/usePeople.js starts with /api, it gets proxied to the backend instead of being served as a static file.

The backend doesn't have a route for /api/hooks/usePeople.js, so it returns 404.

Solution

Option 1: Rename the client folder (Recommended)

Rename the conflicting folder to something that won't match the proxy path:

# Rename api to services (or lib, helpers, etc.)
mv src/client/api src/client/services

# Update all imports
find src/client -name "*.jsx" -o -name "*.js" | xargs sed -i '' 's|from.*['"'"'"]\.\.\/api|from "../services|g'

Option 2: Use a different proxy path

Change the proxy path to something more specific:

// vite.config.js
server: {
  proxy: {
    '/api/v1': {  // More specific path
      target: 'http://localhost:3001',
      changeOrigin: true,
    },
  },
}

Option 3: Configure proxy to exclude certain patterns

Use a custom function to exclude certain paths:

server: {
  proxy: {
    '/api': {
      target: 'http://localhost:3001',
      changeOrigin: true,
      bypass: (req) => {
        // Don't proxy requests for JS/TS files
        if (req.url.match(/\.(js|jsx|ts|tsx|mjs)$/)) {
          return req.url;
        }
      },
    },
  },
}

Verification

After applying the fix:

  1. Clear Vite's cache: rm -rf node_modules/.vite
  2. Restart the dev server: npm run dev
  3. Check browser console - 404 errors should be gone
  4. Verify the app loads and API calls still work

Test both:

  • Frontend file serving: curl http://localhost:5173/services/hooks/usePeople.js should return JavaScript
  • API proxying: curl http://localhost:5173/api/people should return JSON from backend

Example

Before (broken):

src/client/
├── api/                    ← Conflicts with proxy
│   └── hooks/
│       └── usePeople.js
├── pages/
│   └── Directory.jsx       ← import from '../api/hooks/usePeople.js'

vite.config.js:
  proxy: { '/api': 'http://localhost:3001' }

Result: Browser gets 404 for usePeople.js

After (fixed):

src/client/
├── services/               ← Renamed to avoid conflict
│   └── hooks/
│       └── usePeople.js
├── pages/
│   └── Directory.jsx       ← import from '../services/hooks/usePeople.js'

vite.config.js:
  proxy: { '/api': 'http://localhost:3001' }  ← Unchanged

Result: Frontend files served correctly, API still proxied

Notes

  • This issue is not specific to React—it affects any Vite project with proxies
  • Common conflicting folder names: api, graphql, socket, ws
  • The issue only manifests in development (Vite dev server); production builds don't have this problem
  • If using TypeScript path aliases, ensure they also avoid proxy path conflicts
  • Always clear Vite's cache (node_modules/.vite) after changing folder structure

Related Issues

  • Similar issues can occur with other dev servers (webpack-dev-server, Create React App)
  • If using a monorepo, check proxy configs in both root and package-level configs

Signals

GitHub stars
265
Forks
55
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
vite-proxy-folder-name-conflict
Source
github.com/divinevideo/divine-mobile