# Fixing Broken Asset Paths After Lovable Deployment

- Tool: Lovable
- Difficulty: Intermediate
- Fix time: ~10 min
- Compatibility: All Lovable projects deployed to external hosting
- Last updated: March 2026

## TL;DR

Images, fonts, and other assets return 404 errors after deploying a Lovable project because their file paths are wrong in the built output. Fix this by placing all assets in the /public folder, using root-relative paths starting with / in your code, verifying the Vite base path in vite.config.ts is correct, and clearing CDN caches after deployment. Assets in /src are processed by Vite and get hashed filenames, while assets in /public are copied as-is.

## Why asset paths break when deploying Lovable projects

Lovable projects use Vite as the build tool, which handles assets differently depending on where they are stored. Files in the /public folder are copied directly to the build output with their original names and paths. Files in /src are processed by Vite, which adds content hashes to filenames (like logo-a3b4c5d.png) for cache busting.

Asset 404s happen when your code references a path that does not exist in the deployed build. Common scenarios include: using relative paths (./images/logo.png) instead of root-relative paths (/images/logo.png), referencing /src assets with their original names instead of the hashed versions, or setting an incorrect base path in vite.config.ts.

This problem is invisible in the Lovable preview because the development server resolves paths differently than a production server. An asset that works perfectly in preview may return 404 after deployment if the path is not configured for production.

- Assets are in /src instead of /public, so Vite hashes the filenames and the original paths no longer work
- Code uses relative paths (./image.png) that break when accessed from nested routes
- The base path in vite.config.ts is set incorrectly for the hosting platform
- CDN or hosting platform serves cached versions of old assets while the new build references new hashed filenames
- Asset files were not committed to GitHub and are missing from the deployed build

## Error messages you might see

**GET https://myapp.lovable.app/images/logo.png 404 (Not Found)**

The browser cannot find the image at the expected path. The file may be missing from the /public folder, or the path in your code does not match the actual file location in the build output.

**Failed to load resource: the server responded with a status of 404**

A generic 404 for any asset (image, font, JSON file). Check the exact URL in the error to determine which file is missing and where the browser expects to find it.

**Module not found: Can't resolve './assets/image.png'**

Vite cannot find the referenced file during the build process. Either the file does not exist at the specified path, or the path contains a typo. Check the actual file location and update the import.

## Before you start

- A Lovable project deployed to an external hosting platform where assets are not loading
- Access to the browser developer tools (Network tab) to identify which assets return 404
- Dev Mode or GitHub access to check where files are actually located in the project

## How to fix it

### 1. Move assets to the /public folder for direct serving

*Files in /public are copied to the build output as-is, preserving their original paths*

Open your project in Dev Mode or through the GitHub repository. Check where your assets currently live. If images, fonts, or other static files are in /src/assets, they get processed by Vite and receive hashed filenames. Move them to /public instead. Files in /public/images/logo.png become available at /images/logo.png in the deployed app. This is the simplest and most reliable approach for static assets.

Before:

```
// File location: src/assets/images/logo.png
// Import in code:
import logo from "./assets/images/logo.png";
// This works in dev but the hashed filename may cause issues
```

After:

```
// File location: public/images/logo.png
// Reference in code (no import needed):
<img src="/images/logo.png" alt="Logo" />
// The file is served directly at /images/logo.png
```

**Expected result:** The image loads correctly at /images/logo.png in both preview and production deployments.

### 2. Use root-relative paths for all asset references

*Root-relative paths (/path) work from any route, while relative paths (./path) break on nested routes*

Replace all relative asset paths with root-relative paths starting with /. A relative path like ./images/logo.png resolves differently depending on the current URL. If the user is on /dashboard/settings, the browser looks for /dashboard/settings/images/logo.png, which does not exist. A root-relative path /images/logo.png always resolves to the same location regardless of the current route.

Before:

```
// Relative path — breaks on nested routes
<img src="./images/logo.png" alt="Logo" />
<img src="images/hero.jpg" alt="Hero" />
<link rel="stylesheet" href="styles/custom.css" />
```

After:

```
// Root-relative paths — work from any route
<img src="/images/logo.png" alt="Logo" />
<img src="/images/hero.jpg" alt="Hero" />
<link rel="stylesheet" href="/styles/custom.css" />
```

**Expected result:** Assets load correctly regardless of which page or route the user is viewing.

### 3. Verify the Vite base path configuration

*An incorrect base path in vite.config.ts causes all asset URLs to be prefixed with the wrong path*

Open vite.config.ts in your project. Check the base property. For most deployments, this should be '/' (the default). If you are deploying to a subdirectory (like github.io/my-project/), set base to '/my-project/'. An incorrect base path is one of the most common causes of asset 404s after deployment because it prepends the wrong prefix to every asset URL in the built HTML.

Before:

```
// vite.config.ts — incorrect base path
export default defineConfig({
  base: '/wrong-path/',
  plugins: [react()],
});
```

After:

```
// vite.config.ts — correct base path for root deployment
export default defineConfig({
  base: '/',
  plugins: [react()],
});
```

**Expected result:** Asset URLs in the built HTML start with / (or your correct subdirectory path), matching the actual server structure.

### 4. Clear CDN caches and verify the build output

*CDN caching can serve old asset references while the new build expects new filenames*

After deploying, clear any CDN or hosting caches. On Vercel, deployments automatically invalidate the cache. On Netlify, go to Site settings > Build & deploy > Post processing and clear the cache. On Cloudflare, purge the cache. Then check the build output: in the dist/ folder, verify that all expected assets exist. Open the browser's Network tab and look for any 404 responses on asset requests. If debugging asset paths across multiple deployment environments gets complex, RapidDev's engineers have resolved asset issues across 600+ Lovable projects.

Before:

```
// Old deployment serves: logo-abc123.png
// New deployment references: logo-def456.png
// CDN still serves the old page pointing to the old hash
```

After:

```
// After cache clear:
// Browser requests logo-def456.png
// Server returns the correct new file
// No 404 errors in the Network tab
```

**Expected result:** All assets load correctly with no 404 errors in the browser's Network tab.

## Complete code example

File: `vite.config.ts`

```typescript
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react-swc";
import path from "path";

export default defineConfig({
  // Base path: '/' for root deployment, '/subdir/' for subdirectory
  base: "/",
  plugins: [react()],
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "./src"),
    },
  },
  build: {
    // Output directory for the production build
    outDir: "dist",
    // Generate source maps for debugging (optional)
    sourcemap: false,
    // Asset handling
    assetsDir: "assets",
    // Inline assets smaller than 4kb as base64
    assetsInlineLimit: 4096,
    rollupOptions: {
      output: {
        // Organize built assets into subdirectories
        assetFileNames: "assets/[name]-[hash][extname]",
        chunkFileNames: "assets/[name]-[hash].js",
        entryFileNames: "assets/[name]-[hash].js",
      },
    },
  },
});
```

## Best practices

- Place all static assets (images, fonts, icons) in the /public folder for predictable paths in production
- Always use root-relative paths starting with / for assets in /public — never use relative paths
- For assets imported in JavaScript (icons used as React components), keep them in /src and use import statements
- Set the base path in vite.config.ts to match your deployment URL structure — '/' for root, '/subdir/' for subdirectories
- After deployment, check the browser Network tab for 404 errors to identify any missing assets
- Commit all asset files to GitHub before deploying — files not in the repo will not be in the build
- Use Supabase Storage for user-uploaded files instead of the /public folder — these survive across deployments
- Clear hosting platform caches after deploying if asset URLs have changed

## Frequently asked questions

### Why do my images work in Lovable preview but not after deployment?

The development server resolves paths differently than a production server. Relative paths like ./images/logo.png work in preview because the dev server tries multiple locations. In production, the path must match exactly. Move assets to /public and use root-relative paths like /images/logo.png.

### Should I put assets in /public or /src in a Lovable project?

Use /public for static assets you reference by URL (images in HTML, favicon, fonts). Use /src for assets you import in JavaScript (SVG icons used as React components). Files in /public keep their original paths; files in /src get hashed filenames.

### What is the Vite base path and when should I change it?

The base property in vite.config.ts sets the prefix for all asset URLs in the built HTML. Keep it as '/' for standard deployments. Change it only if deploying to a subdirectory, like '/my-project/' for GitHub Pages.

### How do I find which assets are returning 404 after deployment?

Open the browser developer tools, go to the Network tab, and reload the deployed page. Filter by status code or look for red entries. Each 404 shows the exact URL the browser tried to load, helping you identify the broken path.

### Do I need to clear the CDN cache after deploying?

Sometimes. Vite adds content hashes to filenames, so new builds get new URLs that bypass caches. But if your HTML file is cached, it may still reference old asset hashes. On Vercel, caches are cleared automatically. On other platforms, you may need to purge manually.

### What if I can't fix this myself?

If your deployment has many broken asset paths across different components and hosting configurations, RapidDev's engineers can audit and fix all of them. They have resolved asset path issues across 600+ Lovable deployments.

---

Source: https://www.rapidevelopers.com/lovable-issues/fixing-broken-asset-paths-after-lovable-deployment
© RapidDev — https://www.rapidevelopers.com/lovable-issues/fixing-broken-asset-paths-after-lovable-deployment
