Public Folder Fails – The Path You Thought You Knew


There you were. Confidently importing that PNG.
Everything worked on localhost.
Then you deployed.
❌ “GET /logo.png 404 (Not Found)”
❌ “Favicon not loading”
❌ Your UI now looks like it time-traveled to 1996
Welcome to the misunderstood chaos of the public/
folder — where paths lie, and relative becomes irrelevant.
😅 Wait… What’s the public/
Folder For?
In frameworks like React (Vite, CRA) and Next.js, the public/
folder is used for:
Static assets (images, fonts, videos)
Robots.txt, sitemap, favicons
Files you want served as-is, without being bundled
Anything in public/
gets served from the root of your domain.
🚨 The Common Mistakes
❌ 1. Relative Paths Gone Wild
<img src="logo.png" />
Works on localhost because you're at /
, but in production? Your app could be at /subdir/
or on a CDN.
Fix: Always start with
/
<img src="/logo.png" /> ✅
❌ 2. Using public/
in the Path
<img src="/public/logo.png" /> ❌
This is like putting /fridge/fridge/milk
. Just… no.
Files in public/
are served from the root — so use /logo.png
, not /public/logo.png
.
❌ 3. Mixing Public and Import in Vite/React
import logo from "../public/logo.png" ❌
You can’t import directly from public/
. That folder is invisible to the module system.
If you want to import:
Put the asset in
src/assets/
Or use a proper
/
-based path frompublic/
How to Do It Right
✅ Use /
Absolute Paths for Public Files
<img src="/banner.jpg" />
This works whether your app is at the root or being hosted on a CDN (if configured correctly).
✅ Use next/image
or Vite’s asset handling for Optimized Loading
In Next.js:
import Image from "next/image";
<Image src="/hero.png" width={300} height={200} />
This handles caching, resizing, and optimization.
✅ Check Your Base Path on Deployment
Deploying to /my-app/
on GitHub Pages? You must adjust your base path.
- In Vite:
base: "/my-app/"
- In Next.js:
basePath: "/my-app",
✅ Check MIME Types & Case Sensitivity
Some platforms treat /Image.PNG
and /image.png
differently.
Always lowercase file names and extensions for sanity.
Final Thoughts
Your assets deserve better. Give them:
✅ The right path
✅ The right folder
✅ A working deploy that doesn’t make your landing page look like ASCII art
If it worked on localhost, that means nothing. Production is the final boss — treat it with respect.
📚 This was another episode of It Worked in Dev — where asset paths aren’t what they seem, and 404s haunt even the purest code.
Subscribe to my newsletter
Read articles from Faiaz Khan directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Faiaz Khan
Faiaz Khan
Hey! I'm Faiaz — a frontend developer who loves writing clean, efficient, and readable code (and sometimes slightly chaotic code, but only when debugging). This blog is my little corner of the internet where I share what I learn about React, JavaScript, modern web tools, and building better user experiences. When I'm not coding, I'm probably refactoring my to-do list or explaining closures to my cat. Thanks for stopping by — hope you find something useful or mildly entertaining here.