Skip to main content
RapidDev - Software Development Agency
v0-issues

Uploading and accessing static media files in v0

Static media files in V0 projects belong in the public/ directory at the project root. Reference them with absolute paths like /images/logo.png — not relative paths or import statements. After export, verify the public/ folder transferred correctly because V0's sandbox may reference placeholder URLs that do not resolve in production.

Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate6 min read10-20 minutesV0 with Next.js App Router, Vercel deploymentMarch 2026RapidDev Engineering Team
TL;DR

Static media files in V0 projects belong in the public/ directory at the project root. Reference them with absolute paths like /images/logo.png — not relative paths or import statements. After export, verify the public/ folder transferred correctly because V0's sandbox may reference placeholder URLs that do not resolve in production.

Why static files fail to load in V0 projects

V0 generates code that references images and media using paths that work inside its preview sandbox but may not resolve after deployment or export. The sandbox uses esm.sh for module resolution and may serve placeholder assets from temporary URLs. When you export the project, these URLs break. Additionally, V0 sometimes generates import statements for images instead of using the Next.js public/ directory pattern, causing build errors in strict TypeScript configurations.

  • V0 generates placeholder image URLs (like /placeholder.svg) that do not exist in your deployed project
  • Files uploaded to V0 may not persist correctly in the public/ directory after export
  • Using import statements for static assets instead of public/ directory references
  • Incorrect file paths — relative paths like ./images/logo.png fail in Next.js App Router
  • Case-sensitive file systems on deployment servers rejecting Logo.PNG when code references logo.png

Error messages you might see

GET /images/logo.png 404 (Not Found)

The file does not exist in the public/ directory or the path is incorrect. Next.js serves static files from public/ at the root URL path.

Module not found: Can't resolve './assets/hero.jpg'

You are importing an image file as a module. In Next.js App Router, static files should be in public/ and referenced by URL path, or imported using next/image with a proper loader.

Error: Image is missing required "width" property

The Next.js Image component requires explicit width and height props for static images, or the fill prop with a positioned parent container.

Before you start

  • A V0 project that needs static images, fonts, or media files
  • Access to the V0 code editor and file explorer
  • Media files ready to upload (images, icons, documents)

How to fix it

1

Create the public/ directory and add your files

Next.js serves files from public/ at the root URL path. A file at public/images/logo.png becomes accessible at /images/logo.png in the browser.

In the V0 file explorer, right-click the project root and create a public/ directory if it does not exist. Create subdirectories like public/images/ for organization. Upload files by clicking the + icon or dragging files into the explorer.

Expected result: Files appear in the file explorer under public/images/ and are accessible in the preview at /images/filename.ext.

2

Replace placeholder image URLs with real asset paths

V0 generates /placeholder.svg or similar placeholder URLs during prototyping. These must be replaced with actual file paths before deployment.

Search your codebase for placeholder references and replace them with paths to your actual files in the public/ directory.

Before
typescript
<img
src="/placeholder.svg"
alt="Hero banner"
className="w-full h-64 object-cover"
/>
After
typescript
import Image from 'next/image';
<Image
src="/images/hero-banner.jpg"
alt="Hero banner"
width={1200}
height={400}
className="w-full h-64 object-cover"
priority
/>

Expected result: The actual image displays in the V0 preview and in production after deployment.

3

Use the Next.js Image component for optimized loading

The next/image component automatically optimizes images with lazy loading, responsive sizing, and WebP conversion on Vercel. Using plain img tags misses these performance benefits.

Replace HTML img tags with the Next.js Image component. Provide width and height for static sizing, or use the fill prop with a relatively positioned parent for fluid layouts.

Before
typescript
<img
src="/images/profile.jpg"
alt="Profile photo"
className="rounded-full w-16 h-16"
/>
After
typescript
import Image from 'next/image';
<div className="relative w-16 h-16">
<Image
src="/images/profile.jpg"
alt="Profile photo"
fill
className="rounded-full object-cover"
/>
</div>

Expected result: The image loads with automatic optimization. On Vercel, it serves as WebP with appropriate sizing.

4

Verify assets transfer correctly after GitHub export

Files uploaded directly in V0 may not always sync to the GitHub repository, especially binary files. The Git panel tracks code changes but large media files can be missed.

After connecting to GitHub via the Git panel, check that your public/ directory and all media files appear in the repository. If files are missing, re-upload them to the GitHub repository directly or use Git LFS for files larger than 1MB.

Expected result: All files in public/ appear in the GitHub repository and deploy correctly on Vercel.

Complete code example

app/components/MediaGallery.tsx
1'use client';
2
3import Image from 'next/image';
4import { useState } from 'react';
5import { Card, CardContent } from '@/components/ui/card';
6import { Dialog, DialogContent, DialogTrigger } from '@/components/ui/dialog';
7
8interface MediaItem {
9 src: string;
10 alt: string;
11 width: number;
12 height: number;
13}
14
15const mediaItems: MediaItem[] = [
16 { src: '/images/gallery/photo-1.jpg', alt: 'Gallery photo 1', width: 600, height: 400 },
17 { src: '/images/gallery/photo-2.jpg', alt: 'Gallery photo 2', width: 600, height: 400 },
18 { src: '/images/gallery/photo-3.jpg', alt: 'Gallery photo 3', width: 600, height: 400 },
19];
20
21export function MediaGallery() {
22 const [selected, setSelected] = useState<MediaItem | null>(null);
23
24 return (
25 <div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4 p-6">
26 {mediaItems.map((item) => (
27 <Dialog key={item.src}>
28 <DialogTrigger asChild>
29 <Card className="cursor-pointer hover:shadow-lg transition-shadow">
30 <CardContent className="p-0">
31 <Image
32 src={item.src}
33 alt={item.alt}
34 width={item.width}
35 height={item.height}
36 className="rounded-t-lg object-cover w-full"
37 />
38 </CardContent>
39 </Card>
40 </DialogTrigger>
41 <DialogContent className="max-w-3xl">
42 <Image
43 src={item.src}
44 alt={item.alt}
45 width={1200}
46 height={800}
47 className="w-full rounded-lg"
48 />
49 </DialogContent>
50 </Dialog>
51 ))}
52 </div>
53 );
54}

Best practices to prevent this

  • Always place static files in public/ — never import them as JavaScript modules in Next.js App Router projects
  • Use absolute paths starting with / to reference public/ files (e.g., /images/logo.png not ./images/logo.png)
  • Replace all V0-generated /placeholder.svg references before deploying to production
  • Use the Next.js Image component for automatic optimization, lazy loading, and WebP conversion
  • Keep file names lowercase and use hyphens — avoid spaces and special characters for cross-platform compatibility
  • Add width and height props to Image components to prevent Cumulative Layout Shift (CLS)
  • For large media files (over 1MB), consider hosting on a CDN like Vercel Blob or Cloudflare R2 instead of the public/ directory
  • Verify all media files appear in your GitHub repository after connecting via the Git panel

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

I exported a V0 Next.js project and all images show broken icons. The code references /placeholder.svg and some images from /images/. How do I set up the public/ directory correctly and replace placeholder URLs with real image paths?

Frequently asked questions

Where should I put static files in a V0 project?

Place all static files — images, fonts, documents, icons — in the public/ directory at the project root. Files in public/ are served at the root URL path, so public/images/logo.png becomes /images/logo.png in your code.

Why do my images show as broken after deploying from V0?

V0 generates placeholder image paths like /placeholder.svg that do not exist in production. Replace these with actual file paths pointing to images in your public/ directory, and verify the files were included in the GitHub export.

Should I use img tags or the Next.js Image component?

Use the Next.js Image component from next/image for most cases. It provides automatic lazy loading, responsive sizing, and WebP conversion on Vercel. Use plain img tags only for external URLs that you cannot configure in next.config.js.

How do I serve static files from a CDN instead of public/?

For files larger than 1MB or frequently accessed assets, upload them to Vercel Blob, Cloudflare R2, or AWS S3. Reference the CDN URL directly in your Image component and add the CDN domain to the images.remotePatterns array in next.config.js.

Can I upload files directly in the V0 editor?

Yes. Use the + icon in the file explorer or drag files directly into the public/ directory. However, verify that uploaded binary files sync correctly to GitHub if your project is connected via the Git panel.

Why does Next.js Image require width and height props?

The width and height props prevent Cumulative Layout Shift (CLS) by reserving space before the image loads. Alternatively, use the fill prop with a relatively positioned parent container for fluid layouts where the image should fill its container.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your issue.

Book a free consultation

Need help with your Lovable project?

Our experts have built 600+ apps and can solve your issue fast. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.