Next.js Lesson 7 – Static Assets | Dataplexa
LESSON 7

Static Assets

Handle images, icons, and files in your NewsWave site using Next.js asset optimization and the public directory.

Static assets power modern websites. Every logo, hero image, favicon, and PDF download lives somewhere in your project. Next.js gives you two ways to handle these files — each with different superpowers. Unlike plain React where you import everything or dump files in a public folder, Next.js treats static assets like first-class citizens. The framework optimizes images automatically, serves files efficiently, and even helps with SEO. The NewsWave team needs a home for their logo, article images, and social media icons.

The Public Directory

The public folder sits at your project root — right next to src and package.json. Everything inside gets served directly at your domain root. Drop a file called logo.png in there, and visitors can access it at /logo.png. Think of public like your website's front desk. Visitors can grab anything you leave there without asking permission. No imports needed. No build process involved. The file path in public becomes the URL path exactly. But this simplicity comes with responsibility. Files in public bypass Next.js optimizations. They get served as-is, no matter how large or unoptimized. Use public for assets that need exact URLs or third-party services that expect specific file locations.
📁 NewsWave Project Structure
📁 newswave/
📁 public/
📄 logo.png
📄 favicon.ico
📄 robots.txt
📁 images/
📄 hero-bg.jpg
📄 placeholder.svg
📁 icons/
📄 twitter.svg
📄 facebook.svg
📁 src/
📁 app/
📄 layout.js
📄 page.js
Now reference these files directly in your components. The public folder becomes invisible in URLs — public/logo.png becomes /logo.png.
// NewsWave header component with logo from public folder
export default function Header() {
  return (
    <header>
      <img 
        src="/logo.png"           // Direct path to public/logo.png
        alt="NewsWave"           // Always include alt text
        width={120}              // Specify dimensions
        height={40} 
      />
    </header>
  )
}
localhost:3000 — NewsWave

What just happened?

The src attribute points directly to the public folder without mentioning "public" in the path. Next.js serves the file at your domain root. Try this: Create a public/test.txt file with some text, then visit /test.txt in your browser.

Common Public Folder Files

Certain files belong in public by convention. Search engines, social platforms, and browsers expect them at specific URLs. Fighting this expectation creates more work than following it.

SEO Files

favicon.ico, robots.txt, sitemap.xml — search engines and browsers expect these at your domain root.

Social Assets

og-image.jpg, apple-touch-icon.png — social media platforms and mobile devices grab these automatically.

Downloads

PDFs, ZIP files, documents — anything users download directly without processing.

Third-party Assets

Verification files, service worker scripts — external services expect exact file paths.

Next.js Image Component

Images make or break website performance. A single unoptimized photo can slow your site to a crawl. Next.js solves this with the built-in Image component — a supercharged replacement for regular HTML img tags. The Image component automatically optimizes, resizes, and serves images in modern formats. It lazy loads images as users scroll, preventing unnecessary downloads. The component even generates responsive images for different screen sizes without you writing media queries. Unlike regular img tags that serve whatever file you give them, the Image component processes images on-demand. A user with a phone gets a small WebP image. A user with a 4K monitor gets a larger version. Same image source, different delivery.
// Import the Next.js Image component first
import Image from 'next/image'

export default function ArticleCard() {
  return (
    <div>
      <Image
        src="/images/hero-bg.jpg"     // Path from public folder
        alt="Breaking news today"     // Required for accessibility
        width={800}                   // Required: original width
        height={400}                  // Required: original height
        priority                      // Load immediately (above fold)
      />
      <h3>Major Tech Breakthrough Announced</h3>
    </div>
  )
}
localhost:3000 — NewsWave

What just happened?

The Image component requires width and height props to prevent layout shifts during loading. The priority prop tells Next.js to load this image immediately instead of waiting for lazy loading. Try this: Remove the priority prop to see lazy loading in action on longer pages.

Responsive Images

Modern websites need images that adapt to different screen sizes. A tiny phone shouldn't download the same massive image as a desktop computer. The Image component handles this automatically with the fill and sizes props. The fill prop makes images stretch to fill their container — like CSS background images but with all the Next.js optimizations. You define the container size with CSS, and the image adapts accordingly.
// Responsive hero image that fills its container
import Image from 'next/image'

export default function HeroSection() {
  return (
    <div style={{
      position: 'relative',        // Required for fill images
      width: '100%',              // Container controls size
      height: '400px'             // Set container height
    }}>
      <Image
        src="/images/hero-bg.jpg"
        alt="NewsWave hero background"
        fill                        // Fill the container
        style={{ objectFit: 'cover' }}  // How image fits container
        priority                    // Load immediately
      />
      <h1>Welcome to NewsWave</h1>   {/* Content over image */}
    </div>
  )
}
localhost:3000 — NewsWave
The objectFit style controls how the image fits inside its container — just like CSS background-size. Use cover to crop the image while maintaining aspect ratio, or contain to show the entire image with possible empty space.

Importing Assets

Sometimes you want to import assets directly into your JavaScript — like icons in component libraries or images that change based on application state. Next.js supports importing images and other assets just like ES6 modules. Imported assets get processed through the build system. Next.js generates optimized filenames with hashes for cache busting. When you change an image, the filename changes automatically, forcing browsers to download the fresh version. This approach works well for assets that are tightly coupled to specific components. Think logos, icons, or illustrations that belong to particular features rather than general content.
// Import images like any other module
import logo from '/public/logo.png'
import heroImage from '/public/images/hero-bg.jpg'
import Image from 'next/image'

export default function ImportedImages() {
  return (
    <div>
      <Image 
        src={logo}               // Use imported image object
        alt="NewsWave logo"      // Always include alt text
        width={150}             // Set display size
        height={50}
      />
      <Image 
        src={heroImage}
        alt="Hero background"
        width={600}
        height={300}
      />
    </div>
  )
}
localhost:3000 — NewsWave

What just happened?

Imported images become objects with metadata Next.js can use for optimization. The build process generates unique filenames and handles caching automatically. Try this: Check the Network tab to see how Next.js renames imported images with hash values.

Asset Organization Strategy

Large projects need consistent asset organization. Without a system, you end up with images scattered everywhere, broken links, and confused teammates. The NewsWave team needs a structure that scales from launch to thousands of articles. Create folders that mirror your site structure. Put article images in public/articles/, category banners in public/categories/, and UI elements in public/ui/. This organization makes assets easy to find and maintain. But avoid going too deep. Folders more than 2-3 levels deep become harder to navigate than flat structures. Find the balance between organization and simplicity for your team size and project complexity.
📁 NewsWave Asset Organization
📁 public/
📄 favicon.ico
📄 logo.png
📄 robots.txt
📁 articles/
📄 tech-breakthrough-2024.jpg
📄 climate-summit-report.jpg
📁 categories/
📄 tech-banner.jpg
📄 world-banner.jpg
📁 ui/
📄 placeholder.svg
📄 loading-spinner.gif
📁 social/
📄 og-image.jpg
📄 twitter-card.jpg
Name files descriptively instead of generically. tech-breakthrough-2024.jpg tells you more than image1.jpg. Include dates or version numbers for assets that change over time. Use lowercase and hyphens for web-safe filenames that work across all systems.

Performance Considerations

Every asset affects your site's loading speed. Large images slow down page loads. Too many small images create network congestion. The key is finding the sweet spot between quality and performance. Optimize images before adding them to your project. Tools like ImageOptim, TinyPNG, or Squoosh can reduce file sizes by 60-80% without visible quality loss. Next.js optimizes further, but starting with smaller files gives better results. Consider your audience's internet speeds. A news site targeting global users needs more aggressive optimization than an internal company tool. Monitor your site's Core Web Vitals to see how assets affect real user experience.

Performance Warning

Loading multiple large images without optimization can make your NewsWave homepage load in 10+ seconds. Users abandon sites that take longer than 3 seconds to load. Always test your pages with slow network conditions.

Building a Complete Media System

Real applications need more than basic image handling. The NewsWave team wants article thumbnails, social media sharing images, and author avatars. Each image type has different requirements and optimization strategies. Start with a reusable media component that handles common image scenarios. This component can set default sizes, loading behavior, and fallbacks while keeping your page components clean and focused.
// Reusable media component for NewsWave articles
import Image from 'next/image'

export default function ArticleImage({ 
  src, 
  alt, 
  priority = false,     // Most images should lazy load
  className = '' 
}) {
  return (
    <div className={`article-image ${className}`}>
      <Image
        src={src}
        alt={alt}
        width={800}          // Standard article width
        height={400}         // 2:1 aspect ratio
        priority={priority}  // Only for above-fold images
        style={{ 
          width: '100%',
          height: 'auto',     // Maintain aspect ratio
          borderRadius: '8px' 
        }}
      />
    </div>
  )
}
localhost:3000 — NewsWave
Now use this component consistently across your application. Every article image gets the same optimization, sizing, and styling without repeating code. When you need to change how article images work, update one component instead of dozens of files.
// Use the ArticleImage component in your pages
import ArticleImage from './components/ArticleImage'

export default function HomePage() {
  return (
    <div>
      <h1>Latest News</h1>
      
      <article>
        <ArticleImage 
          src="/articles/tech-breakthrough-2024.jpg"
          alt="Scientists announce quantum computing breakthrough"
          priority={true}  // First article loads immediately
        />
        <h2>Quantum Computing Breakthrough Changes Everything</h2>
        <p>Research teams across the globe report major advances...</p>
      </article>
      
      <article>
        <ArticleImage 
          src="/articles/climate-summit-report.jpg"
          alt="World leaders at climate summit meeting"
          // priority defaults to false for lazy loading
        />
        <h2>Climate Summit Reaches Historic Agreement</h2>
        <p>After weeks of negotiations, world leaders have...</p>
      </article>
    </div>
  )
}
Terminal
$ npm run dev
▲ Next.js 14.0.0
- Local: http://localhost:3000
✓ Ready in 2.1s
○ (Static) automatically optimized as static HTML
◐ (SSG) automatically generated as static HTML + JSON

What just happened?

The reusable component standardizes image handling across your site. The first article loads immediately with priority, while others lazy load for better performance. Next.js automatically optimizes each image based on the user's device. Try this: Add more articles and scroll to see lazy loading in action.

Static assets form the foundation of engaging web experiences. Master the public directory for files that need direct access. Use the Image component for photos and graphics that need optimization. Organize assets logically and think about performance from day one. The NewsWave site now handles logos, article images, and social media assets efficiently. Users get fast loading times while editors can easily add new visual content. Your Next.js applications are ready to deliver rich media experiences at scale.

Quiz

1. The NewsWave team puts their logo.png in the public folder. How do visitors access this file?


2. What advantage does the Next.js Image component have over regular HTML img tags?


3. When should you use the priority prop on Next.js Image components in NewsWave?


Up Next: CSS and Styling

Transform your NewsWave site with modern CSS approaches, Tailwind integration, and component styling strategies.