Falytom logoFALYTOM
Games
ToolsUI ComponentsServicesProductsAbout
menu
  1. Home
  2. /Web Development
  3. /Nextjs
  4. /Static Assets
Your Progress0%
0 of 70 completed

NextJS Topics

Getting Started

  • What is Next.js?
  • Next.js vs React - Key Differences
  • Creating Your First Next.js 15 Project
  • Next.js Project Structure Explained
  • App Router vs Pages Router

Routing Fundamentals

  • File-Based Routing Basics
  • Creating Pages with page.tsx
  • Dynamic Routes and Route Parameters
  • Catch-All and Optional Catch-All Routes
  • Route Groups for Organization
  • Parallel Routes
  • Intercepting Routes

Layouts and Pages

  • Understanding Layouts
  • Root Layout and Global Configuration
  • Nested Layouts
  • Templates vs Layouts
  • Loading States with loading.tsx
  • Error Handling with error.tsx

Server and Client Components

  • Understanding Server Components
  • Client Components with 'use client'
  • When to Use Server vs Client Components
  • Component Composition Patterns
  • Passing Props Between Server and Client
  • Server Component Patterns and Best Practices

Data Fetching

  • Fetching Data in Server Components
  • Parallel and Sequential Data Fetching
  • Data Fetching Patterns and Strategies
  • Caching and Revalidation
  • Revalidate and Cache Tags
  • Handling Loading and Error States in Data Fetching

Navigation and Links

  • Link Component Basics
  • useRouter Hook for Programmatic Navigation
  • usePathname and useSearchParams Hooks
  • Active Links and Navigation States
  • Redirects and Navigation Guards

Styling in Next.js

  • CSS Modules in Next.js
  • Tailwind CSS Setup and Configuration
  • Global Styles and CSS Variables
  • Next.js Font Optimization

Images and Media

  • Next.js Image Component Basics
  • Image Optimization and Best Practices
  • Working with Static Assets

Forms and Data Mutations

  • Understanding Server Actions
  • Form Handling with Server Actions
  • Form Validation and Error Handling
  • useFormStatus and useFormState Hooks
  • Revalidating Data After Mutations
  • Optimistic Updates

Metadata and SEO

  • Static Metadata Configuration
  • Dynamic Metadata Generation
  • Open Graph and Social Media Cards
  • Sitemap and Robots.txt

API Routes and Route Handlers

  • Route Handlers Introduction
  • GET and POST Request Handlers
  • Dynamic API Routes
  • Request and Response Objects
  • API Error Handling and Status Codes

Middleware and Advanced Features

  • Introduction to Middleware
  • Authentication with Middleware
  • Environment Variables and Configuration
  • Streaming and Suspense
  • Not Found and Global Error Pages

Deployment and Optimization

  • Understanding Static and Dynamic Rendering
  • generateStaticParams for Static Generation
  • Build and Production Optimization
  • Deploying to Vercel
  • Alternative Deployment Options
  • Performance Monitoring and Analytics

Real-World Projects

  • Project 1: E-commerce Product Catalog
  • Project 2: Dashboard with Authentication

Working with Static Assets

Managing static files and resources in Next.js

Every application needs static assets—images, fonts, documents, icons, and more. Next.js provides the /public folder for static files that are served directly without processing. Understanding when to use public vs imports, how to organize assets efficiently, and best practices for different file types will keep your project maintainable and performant. Let's master static asset management!

The Public Folder

What is the Public Folder?

The /public folder is for static assets served at the root URL path:

Public Folder Characteristics

  • Location: At project root (not in /app)
  • Served at: Root path (/)
  • No processing: Files served as-is
  • Build time: Copied to build output
  • Caching: Efficiently cached by CDNs

Basic Usage

TYPESCRIPT
// File structure:
// /public/images/logo.png
// /public/documents/guide.pdf
// /public/favicon.ico

// Referencing in code:
import Image from 'next/image';

export function Logo() {
  return (
    <Image
      src="/images/logo.png"
      alt="Logo"
      width={200}
      height={50}
    />
  );
}

// Download link
export function DownloadLink() {
  return (
    <a href="/documents/guide.pdf" download>
      Download Guide
    </a>
  );
}

// Favicon (automatic)
// Next.js automatically serves /public/favicon.ico

// ✅ Reference with / (root path)
// ✅ Omit /public in URLs
// ✅ Direct access from browser

⚠️ Important: Start Paths with /

Always reference public files starting with /. Use /images/logo.png, not images/logo.png or public/images/logo.png.

Organizing Static Assets

Recommended Folder Structure

BASH
public/
├── images/                 # Images
│   ├── logo.svg
│   ├── hero.jpg
│   ├── products/          # Product images
│   │   ├── product-1.jpg
│   │   └── product-2.jpg
│   └── avatars/           # User avatars
│       └── default.png
├── icons/                 # Icons and favicons
│   ├── favicon.ico
│   ├── apple-touch-icon.png
│   ├── android-chrome-192x192.png
│   └── android-chrome-512x512.png
├── fonts/                 # Custom fonts (if not using next/font)
│   ├── CustomFont.woff2
│   └── CustomFont.woff
├── documents/             # PDFs and documents
│   ├── terms.pdf
│   ├── privacy.pdf
│   └── user-manual.pdf
├── videos/                # Video files
│   └── intro.mp4
├── audio/                 # Audio files
│   └── notification.mp3
├── data/                  # Static JSON data
│   └── products.json
├── robots.txt            # SEO robots file
├── sitemap.xml           # Sitemap
└── manifest.json         # PWA manifest

// ✅ Organized by file type
// ✅ Nested folders for categories
// ✅ Clear naming convention
// ✅ Easy to find and maintain

Accessing Nested Assets

TYPESCRIPT
import Image from 'next/image';

// Product image in nested folder
export function ProductImage({ id }: { id: string }) {
  return (
    <Image
      src={`/images/products/product-${id}.jpg`}
      alt={`Product ${id}`}
      width={600}
      height={600}
    />
  );
}

// Avatar from nested folder
export function UserAvatar({ username }: { username: string }) {
  return (
    <Image
      src={`/images/avatars/${username}.jpg`}
      alt={username}
      width={80}
      height={80}
      className="rounded-full"
    />
  );
}

// Document download
export function DocumentLink() {
  return (
    <a href="/documents/terms.pdf" target="_blank" rel="noopener">
      View Terms of Service
    </a>
  );
}

// ✅ Use template literals for dynamic paths
// ✅ Nested folders keep assets organized
// ✅ Clear path structure

Importing vs Public Folder

When to Import Images

app/components/Header.tsx
import Image from 'next/image';
import logoImage from '../assets/logo.png';

export function Header() {
  return (
    <Image
      src={logoImage}
      alt="Company Logo"
      placeholder="blur"
      // Blur placeholder automatic for imports!
    />
  );
}

// Benefits of importing:
// ✅ Automatic blur placeholder generation
// ✅ Build-time optimization
// ✅ Width/height automatic from file
// ✅ Type safety (TypeScript knows file exists)
// ✅ Webpack/bundler can optimize

// Use imports for:
// ✅ Critical images (hero, logo)
// ✅ Images with known paths at build time
// ✅ Images needing blur placeholders

When to Use Public Folder

TYPESCRIPT
import Image from 'next/image';

export function DynamicProductImage({ productId }: { productId: string }) {
  return (
    <Image
      src={`/images/products/${productId}.jpg`}
      alt="Product"
      width={600}
      height={600}
    />
  );
}

// Benefits of public folder:
// ✅ Dynamic paths at runtime
// ✅ No build processing needed
// ✅ Direct CDN serving
// ✅ Can add files after build
// ✅ Works with user uploads

// Use public folder for:
// ✅ Dynamic image paths
// ✅ Large number of images
// ✅ User-uploaded content
// ✅ Files that change frequently
// ✅ Non-image assets (PDFs, videos, etc.)

Comparison Table

FeatureImportPublic Folder
Blur Placeholder✅ Automatic❌ Manual
Dynamic Paths❌ No✅ Yes
Type Safety✅ Yes❌ No
Auto Width/Height✅ Yes❌ Manual
CDN Friendly⚠️ OK✅ Excellent
Add After Build❌ No✅ Yes

Common Asset Types

1. Favicon and Icons

BASH
public/
├── favicon.ico              # Browser favicon (16x16, 32x32)
├── apple-touch-icon.png     # Apple touch icon (180x180)
├── icon-192.png            # PWA icon (192x192)
├── icon-512.png            # PWA icon (512x512)
└── manifest.json           # PWA manifest

// Generate at https://realfavicongenerator.net/
app/layout.tsx
export const metadata = {
  icons: {
    icon: '/favicon.ico',
    apple: '/apple-touch-icon.png',
  },
};

// Or manually in HTML:
<head>
  <link rel="icon" href="/favicon.ico" />
  <link rel="apple-touch-icon" href="/apple-touch-icon.png" />
</head>

// ✅ Next.js automatically serves /favicon.ico
// ✅ Place in /public root
// ✅ Generate multiple sizes

2. Documents (PDFs)

TYPESCRIPT
// Store in /public/documents/
export function DocumentLinks() {
  return (
    <div className="space-y-4">
      {/* Open in new tab */}
      
        href="/documents/terms.pdf"
        target="_blank"
        rel="noopener noreferrer"
        className="text-blue-600 hover:underline"
      >
        Terms of Service
      </a>

      {/* Download directly */}
      
        href="/documents/guide.pdf"
        download="user-guide.pdf"
        className="text-blue-600 hover:underline"
      >
        Download User Guide
      </a>

      {/* Embed PDF */}
      <iframe
        src="/documents/embedded.pdf"
        width="100%"
        height="600px"
        className="border rounded-lg"
      />
    </div>
  );
}

// ✅ Direct links to PDFs
// ✅ download attribute for downloads
// ✅ target="_blank" to open in new tab

3. Videos and Audio

TYPESCRIPT
// Store in /public/videos/ and /public/audio/
export function MediaExamples() {
  return (
    <div className="space-y-8">
      {/* Video */}
      <video
        controls
        width="100%"
        poster="/images/video-poster.jpg"
        className="rounded-lg"
      >
        <source src="/videos/intro.mp4" type="video/mp4" />
        <source src="/videos/intro.webm" type="video/webm" />
        Your browser doesn't support video.
      </video>

      {/* Audio */}
      <audio controls className="w-full">
        <source src="/audio/podcast.mp3" type="audio/mpeg" />
        <source src="/audio/podcast.ogg" type="audio/ogg" />
        Your browser doesn't support audio.
      </audio>

      {/* Background video */}
      <video
        autoPlay
        muted
        loop
        playsInline
        className="absolute inset-0 w-full h-full object-cover"
      >
        <source src="/videos/background.mp4" type="video/mp4" />
      </video>
    </div>
  );
}

// ✅ Multiple formats for compatibility
// ✅ poster for video preview
// ✅ controls for user control
// ✅ autoPlay, muted, loop for backgrounds

4. Data Files (JSON, CSV)

TYPESCRIPT
// Store in /public/data/
export async function getStaticData() {
  const response = await fetch('/data/products.json');
  const products = await response.json();
  return products;
}

// Or fetch in component
export function DataComponent() {
  const [data, setData] = useState([]);

  useEffect(() => {
    fetch('/data/products.json')
      .then(res => res.json())
      .then(setData);
  }, []);

  return <div>{/* Use data */}</div>;
}

// ✅ Static data files
// ✅ Fetch like any URL
// ✅ Useful for mock data, configs

// ⚠️ For large data or sensitive data:
// Use API routes instead of public folder

5. SEO Files

public/robots.txt
# robots.txt
User-agent: *
Allow: /
Disallow: /admin/
Disallow: /api/

Sitemap: https://example.com/sitemap.xml
public/sitemap.xml
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>https://example.com/</loc>
    <lastmod>2024-01-01</lastmod>
    <priority>1.0</priority>
  </url>
  <url>
    <loc>https://example.com/about</loc>
    <lastmod>2024-01-01</lastmod>
    <priority>0.8</priority>
  </url>
</urlset>
TYPESCRIPT
// Or generate sitemap dynamically
// app/sitemap.ts
export default function sitemap() {
  return [
    {
      url: 'https://example.com',
      lastModified: new Date(),
      changeFrequency: 'yearly',
      priority: 1,
    },
    {
      url: 'https://example.com/about',
      lastModified: new Date(),
      changeFrequency: 'monthly',
      priority: 0.8,
    },
  ];
}

// ✅ robots.txt in /public
// ✅ sitemap.xml in /public or generated
// ✅ Essential for SEO

Practical Examples

Example 1: Logo Component

components/Logo.tsx
import Image from 'next/image';
import Link from 'next/link';

export function Logo() {
  return (
    <Link href="/" className="flex items-center gap-2">
      {/* SVG logo from public */}
      <Image
        src="/images/logo.svg"
        alt="Company Logo"
        width={40}
        height={40}
        priority
      />
      <span className="text-xl font-bold">Company</span>
    </Link>
  );
}

// ✅ SVG in public folder
// ✅ priority for above-fold
// ✅ Link for navigation

Example 2: Product Gallery

components/ProductGallery.tsx
import Image from 'next/image';

interface Product {
  id: string;
  name: string;
  images: string[];
}

export function ProductGallery({ product }: { product: Product }) {
  const [selectedImage, setSelectedImage] = useState(0);

  return (
    <div className="space-y-4">
      {/* Main image */}
      <div className="relative aspect-square">
        <Image
          src={`/images/products/${product.images[selectedImage]}`}
          alt={`${product.name} - View ${selectedImage + 1}`}
          fill
          className="object-cover rounded-lg"
          priority={selectedImage === 0}
        />
      </div>

      {/* Thumbnails */}
      <div className="grid grid-cols-4 gap-2">
        {product.images.map((image, index) => (
          <button
            key={index}
            onClick={() => setSelectedImage(index)}
            className={`relative aspect-square ${
              index === selectedImage ? 'ring-2 ring-blue-500' : ''
            }`}
          >
            <Image
              src={`/images/products/${image}`}
              alt={`${product.name} thumbnail ${index + 1}`}
              fill
              className="object-cover rounded"
            />
          </button>
        ))}
      </div>
    </div>
  );
}

// ✅ Dynamic image paths
// ✅ Multiple views
// ✅ Priority on main image

Example 3: Downloadable Resources

components/Resources.tsx
interface Resource {
  title: string;
  description: string;
  file: string;
  size: string;
  icon: string;
}

export function ResourcesList({ resources }: { resources: Resource[] }) {
  return (
    <div className="grid md:grid-cols-2 gap-6">
      {resources.map((resource) => (
        <div
          key={resource.file}
          className="bg-white p-6 rounded-lg shadow hover:shadow-lg transition"
        >
          <div className="flex items-start gap-4">
            {/* File icon */}
            <div className="w-12 h-12 flex-shrink-0">
              <Image
                src={`/icons/${resource.icon}`}
                alt=""
                width={48}
                height={48}
              />
            </div>

            <div className="flex-1">
              <h3 className="font-bold text-lg mb-1">{resource.title}</h3>
              <p className="text-gray-600 text-sm mb-3">
                {resource.description}
              </p>
              <div className="flex items-center justify-between">
                <span className="text-xs text-gray-500">{resource.size}</span>
                
                  href={`/documents/${resource.file}`}
                  download
                  className="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 text-sm"
                >
                  Download
                </a>
              </div>
            </div>
          </div>
        </div>
      ))}
    </div>
  );
}

// Usage:
const resources = [
  {
    title: "User Manual",
    description: "Complete guide to using our platform",
    file: "user-manual.pdf",
    size: "2.4 MB",
    icon: "pdf-icon.svg",
  },
  // ... more resources
];

// ✅ Icons from public
// ✅ Documents from public
// ✅ Download links

Example 4: Background Video

components/HeroWithVideo.tsx
export function HeroWithVideo() {
  return (
    <section className="relative h-screen overflow-hidden">
      {/* Background video */}
      <video
        autoPlay
        muted
        loop
        playsInline
        className="absolute inset-0 w-full h-full object-cover"
      >
        <source src="/videos/hero-background.mp4" type="video/mp4" />
        <source src="/videos/hero-background.webm" type="video/webm" />
      </video>

      {/* Overlay */}
      <div className="absolute inset-0 bg-black/50" />

      {/* Content */}
      <div className="relative z-10 h-full flex items-center justify-center text-white text-center">
        <div>
          <h1 className="text-6xl font-bold mb-4">
            Welcome to Our Platform
          </h1>
          <p className="text-xl mb-8">
            Experience the future of technology
          </p>
          <button className="px-8 py-4 bg-blue-600 rounded-lg font-bold text-lg hover:bg-blue-700">
            Get Started
          </button>
        </div>
      </div>
    </section>
  );
}

// ✅ autoPlay, muted, loop for background
// ✅ playsInline for mobile
// ✅ Multiple formats for compatibility
// ✅ Overlay for readability

Complete Asset Organization

Recommended structure for all static assets

publicImportant
app

Select a file or folder to see details

Static Asset Best Practices

1. Organize by Type

BASH
// ✅ GOOD: Organized by type
public/
├── images/
├── icons/
├── fonts/
├── documents/
└── videos/

// ❌ BAD: Everything in root
public/
├── logo.png
├── hero.jpg
├── terms.pdf
├── video.mp4
└── icon.svg

// Organized structure is easier to maintain

2. Use Descriptive Names

BASH
// ✅ GOOD: Descriptive names
/images/hero-homepage-2024.jpg
/documents/privacy-policy-v2.pdf
/icons/search-icon.svg

// ❌ BAD: Generic names
/images/img1.jpg
/documents/doc.pdf
/icons/icon2.svg

// Descriptive names are self-documenting

3. Optimize Before Upload

BASH
# Optimize images before adding to public
# Use tools like:
# - TinyPNG (https://tinypng.com)
# - Squoosh (https://squoosh.app)
# - ImageOptim (Mac)

# Example: Compress images
# Original: 4.2 MB
# Optimized: 400 KB (90% smaller)

# ✅ Optimize before deployment
# ✅ Smaller files = faster loading
# ✅ Better user experience

4. Version Critical Files

BASH
// ✅ GOOD: Version in filename
/documents/terms-v2.pdf
/documents/privacy-policy-2024.pdf
/images/logo-v3.svg

// Allows cache busting
<a href="/documents/terms-v2.pdf">Terms</a>

// ✅ Update filename when content changes
// ✅ Forces browsers to fetch new version
// ✅ Avoids cache issues

5. Don't Store Sensitive Data

BASH
# ❌ NEVER in public folder:
# - API keys
# - Passwords
# - Private documents
# - User data
# - Configuration secrets

# Public folder is publicly accessible!
# https://yoursite.com/secret-file.txt

# ✅ Use environment variables instead
# ✅ Use API routes for sensitive data
# ✅ Use databases for user data

Key Takeaways

  • /public folder - at project root for static assets
  • Reference with / - /images/logo.png (omit /public)
  • Organize by type - images, icons, fonts, documents
  • Import vs public - imports for critical, public for dynamic
  • Common assets - favicon, robots.txt, sitemap.xml
  • Optimize first - compress before uploading
  • Descriptive names - self-documenting filenames
  • No sensitive data - public is publicly accessible

🎉 Images and Media Section Complete!

You've completed the Images and Media section! You've mastered:

  • ✅ Next.js Image component basics
  • ✅ Advanced image optimization
  • ✅ Static asset management

You now have complete mastery of images and assets in Next.js! You can optimize images for performance, organize static assets efficiently, and build applications with fast, optimized media. These skills are essential for creating professional, performant Next.js applications.

📁 Asset Management

Good asset organization pays off long-term. Spend time setting up a clear folder structure at the start of your project. Future you will thank present you when you need to find or update assets!

Final Quiz: Static Assets Mastery

Question 1 of 4

Where do static assets go in a Next.js project?

Master static asset management in Next.js! Learn the public folder, imports, and organization best practices.

Previous
Image Optimization and Best Practices
Next
Understanding Server Actions

Continue Your Next.js Journey

Join 2,000+ developers mastering Next.js. Get more advanced tutorials on APIs, forms, and deployment - 100% FREE.

You might also like

UI Components

Ready-made components for your projects

Developer Tools

Boost productivity with handy generators

HTML Game

Learn HTML concepts through interactive gameplay

Join Our Web Development Training Program

Master frontend & backend development with hands-on projects.

NextJS Tutorials

0 of 70 completed

Your Progress0%

Topics

Getting Started

  • What is Next.js?
  • Next.js vs React - Key Differences
  • Creating Your First Next.js 15 Project
  • Next.js Project Structure Explained
  • App Router vs Pages Router

Routing Fundamentals

  • File-Based Routing Basics
  • Creating Pages with page.tsx
  • Dynamic Routes and Route Parameters
  • Catch-All and Optional Catch-All Routes
  • Route Groups for Organization
  • Parallel Routes
  • Intercepting Routes

Layouts and Pages

  • Understanding Layouts
  • Root Layout and Global Configuration
  • Nested Layouts
  • Templates vs Layouts
  • Loading States with loading.tsx
  • Error Handling with error.tsx

Server and Client Components

  • Understanding Server Components
  • Client Components with 'use client'
  • When to Use Server vs Client Components
  • Component Composition Patterns
  • Passing Props Between Server and Client
  • Server Component Patterns and Best Practices

Data Fetching

  • Fetching Data in Server Components
  • Parallel and Sequential Data Fetching
  • Data Fetching Patterns and Strategies
  • Caching and Revalidation
  • Revalidate and Cache Tags
  • Handling Loading and Error States in Data Fetching

Navigation and Links

  • Link Component Basics
  • useRouter Hook for Programmatic Navigation
  • usePathname and useSearchParams Hooks
  • Active Links and Navigation States
  • Redirects and Navigation Guards

Styling in Next.js

  • CSS Modules in Next.js
  • Tailwind CSS Setup and Configuration
  • Global Styles and CSS Variables
  • Next.js Font Optimization

Images and Media

  • Next.js Image Component Basics
  • Image Optimization and Best Practices
  • Working with Static Assets

Forms and Data Mutations

  • Understanding Server Actions
  • Form Handling with Server Actions
  • Form Validation and Error Handling
  • useFormStatus and useFormState Hooks
  • Revalidating Data After Mutations
  • Optimistic Updates

Metadata and SEO

  • Static Metadata Configuration
  • Dynamic Metadata Generation
  • Open Graph and Social Media Cards
  • Sitemap and Robots.txt

API Routes and Route Handlers

  • Route Handlers Introduction
  • GET and POST Request Handlers
  • Dynamic API Routes
  • Request and Response Objects
  • API Error Handling and Status Codes

Middleware and Advanced Features

  • Introduction to Middleware
  • Authentication with Middleware
  • Environment Variables and Configuration
  • Streaming and Suspense
  • Not Found and Global Error Pages

Deployment and Optimization

  • Understanding Static and Dynamic Rendering
  • generateStaticParams for Static Generation
  • Build and Production Optimization
  • Deploying to Vercel
  • Alternative Deployment Options
  • Performance Monitoring and Analytics

Real-World Projects

  • Project 1: E-commerce Product Catalog
  • Project 2: Dashboard with Authentication
Falytom logoFALYTOM

Learn technologies like HTML, CSS, JavaScript, React, NodeJS and more through interactive games, tutorials, components and free tools. Transform your businesses with AI chatbots, SEO-optimized websites, and professional development services.

© 2025 Tomilola Group
  • Facebook logo
  • Twitter logo
  • Instagram logo
  • LinkedIn logo
  • GitHub logo
  • YouTube logo