Fix Astro Asset Path 404 in Static Builds (Base & public/ Issues)
Images and fonts 404 after Astro static build on Vercel/Netlify. Fix base URL, asset imports, and public folder paths.
Tested on: Astro 5.7, deployed to GitHub Pages subpath
Symptom: Images perfect on localhost:4321. Broken on username.github.io/myblog/.
TL;DR
- Use import for src/assets; put static files in public/.
- Set site config base to match deploy subdirectory.
- Check build output dist/ for missing hashed assets.
Root cause
Hardcoded paths:
<img src="/images/logo.png" />
<link rel="icon" href="/favicon.ico" />
On subpath deploy, browser requests https://username.github.io/images/logo.png — wrong. Should be /myblog/images/logo.png.
Fix 1 — configure base
astro.config.mjs:
export default defineConfig({
site: 'https://username.github.io',
base: '/myblog'
});
Fix 2 — use BASE_URL everywhere
---
const logo = `${import.meta.env.BASE_URL}images/logo.png`;
---
<img src={logo} alt="Logo" />
Or Astro's built-in:
---
import logo from '../assets/logo.png';
import { Image } from 'astro:assets';
---
<Image src={logo} alt="Logo" />
Imported assets get hashed paths automatically — preferred method.
Fix 3 — CSS url() paths
Broken:
.hero { background: url('/images/hero.jpg'); }
Fixed:
.hero { background: url('../assets/hero.jpg'); }
Let Vite process the relative path.
Build warning I ignored too long
WARN assets in public/ are not processed by Astro
Files in public/ copy as-is — no base prefix magic for hardcoded HTML references. Use src/assets/ + import.
GitHub Pages deploy
# .github/workflows/deploy.yml
- name: Build
run: npm run build
env:
BASE_URL: /myblog/
astro.config.mjs:
base: import.meta.env.BASE_URL || '/'
Verify before push
npm run build
npx serve dist
# Visit http://localhost:3000/myblog/ — use same base as prod
Result
Broken images in prod: 14 → 0
Favicon 404: fixed
CSS background images: fixed via relative imports
Rule: never hardcode leading-slash asset paths if base might not be /.
FAQ
Why do Astro images 404 after deploy?
Wrong base path, files in src/ referenced as public URLs, or assets not copied to dist during build.
Should I use public/ or src/assets/ in Astro?
src/assets/ for optimized images via astro:assets. public/ for files needing exact URLs without processing.
How do I fix Astro assets on subdirectory deploy?
Set site: 'https://domain.com/subpath/' in astro.config.mjs so generated paths include the prefix.