Next.js Cheatsheet

Images and Fonts

Use this Next.js reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.

next/image — Optimized Images

import Image from 'next/image'

// Local image (width/height auto-inferred from import)
import logo from '@/public/logo.png'

<Image src={logo} alt="Logo" />

// Remote image (width/height required)
<Image
  src="https://example.com/photo.jpg"
  alt="A photo"
  width={800}
  height={600}
/>

Next.js automatically: converts to WebP/AVIF, serves via CDN, lazy-loads by default, prevents CLS by reserving space.

Core Props

PropTypeNotes
srcstring | StaticImportRequired
altstringRequired
widthnumberRequired for remote; inferred for local
heightnumberRequired for remote; inferred for local
fillbooleanFills parent container (no width/height needed)
sizesstringResponsive sizes hint (required with fill)
prioritybooleanPreload; use for LCP image (default: false)
qualitynumber1–100, default 75
placeholder'blur' | 'empty' | 'data:...'Loading state
blurDataURLstringBase64 blur placeholder (auto with local imports)
loading'lazy' | 'eager'Default 'lazy'; use 'eager' with priority
unoptimizedbooleanSkip optimization (for GIFs, SVGs, etc.)
styleCSSPropertiesInline styles
classNamestringClass names
onLoad() => voidCalled when image finishes loading
onError() => voidCalled on load error

Fill Mode (Responsive Images)

Parent must have position: relative (or absolute/fixed) and explicit dimensions.

<div style={{ position: 'relative', width: '100%', height: '400px' }}>
  <Image
    src="/hero.jpg"
    alt="Hero"
    fill
    sizes="100vw"
    style={{ objectFit: 'cover' }}
  />
</div>

With Tailwind:

<div className="relative w-full h-96">
  <Image
    src="/hero.jpg"
    alt="Hero"
    fill
    sizes="100vw"
    className="object-cover"
  />
</div>

sizes Attribute — Responsive Hints

Tell the browser which size image to download at each breakpoint:

<Image
  src="/photo.jpg"
  alt="Photo"
  fill
  sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
/>

Without sizes, the browser assumes the image is always 100vw — this causes downloading unnecessarily large images.

Blur Placeholder

Local images get blur data URL automatically:

import hero from '@/public/hero.jpg'

<Image src={hero} alt="Hero" placeholder="blur" />

Remote images need a manually generated blurDataURL:

<Image
  src="https://example.com/photo.jpg"
  alt="Photo"
  width={800}
  height={600}
  placeholder="blur"
  blurDataURL="data:image/jpeg;base64,/9j/4AA..."   // tiny base64 preview
/>

Priority / LCP Image

// The first visible image should be priority to avoid LCP penalty
<Image src="/hero.jpg" alt="Hero" fill priority />

Allowing Remote Domains

// next.config.ts
const config: NextConfig = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'images.unsplash.com',
        port: '',
        pathname: '/**',
      },
      {
        protocol: 'https',
        hostname: '*.cloudinary.com',   // wildcard subdomain
      },
    ],
  },
}

Image Loader (CDN)

// next.config.ts
const config: NextConfig = {
  images: {
    loader: 'custom',
    loaderFile: './lib/image-loader.ts',
  },
}
// lib/image-loader.ts
export default function cloudinaryLoader({
  src,
  width,
  quality,
}: {
  src: string
  width: number
  quality?: number
}) {
  return `https://res.cloudinary.com/demo/image/upload/w_${width},q_${quality ?? 75}${src}`
}

SVG Images

Next.js does not optimize SVGs by default. Use unoptimized or the @svgr/webpack package:

<Image src="/icon.svg" alt="Icon" width={24} height={24} unoptimized />

Or import SVGs as React components with SVGR:

import Logo from '@/public/logo.svg'
<Logo className="w-8 h-8" />

next/font — Zero-layout-shift Fonts

Fonts are downloaded at build time and self-hosted — no Google Fonts network request at runtime.

Google Fonts

// app/layout.tsx
import { Inter, Roboto_Mono } from 'next/font/google'

const inter = Inter({
  subsets: ['latin'],
  display: 'swap',       // font-display: swap
  variable: '--font-inter', // expose as CSS variable
})

const mono = Roboto_Mono({
  subsets: ['latin'],
  display: 'swap',
  variable: '--font-mono',
})

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en" className={`${inter.variable} ${mono.variable}`}>
      <body className={inter.className}>{children}</body>
    </html>
  )
}

Use the CSS variable in Tailwind:

// tailwind.config.ts
export default {
  theme: {
    extend: {
      fontFamily: {
        sans: ['var(--font-inter)'],
        mono: ['var(--font-mono)'],
      },
    },
  },
}

Font Options

OptionValuesNotes
subsets['latin'], ['cyrillic'], etc.Required for variable fonts
weight'400', ['400', '700'], 'variable'String or array
style'normal', 'italic', ['normal', 'italic']
display'auto' | 'block' | 'swap' | 'fallback' | 'optional'Default 'swap'
variable'--font-name'Exposes as CSS custom property
preloadbooleanDefault true
fallbackstring[]System font fallbacks
adjustFontFallbackbooleanAuto-adjust fallback metrics (default true)

Variable Fonts

import { Inter } from 'next/font/google'

// Variable font (one file, all weights)
const inter = Inter({ subsets: ['latin'] })

Multiple Weights

import { Roboto } from 'next/font/google'

const roboto = Roboto({
  weight: ['300', '400', '500', '700'],
  subsets: ['latin'],
})

Local Fonts

import localFont from 'next/font/local'

const myFont = localFont({
  src: [
    { path: './fonts/MyFont-Regular.woff2', weight: '400', style: 'normal' },
    { path: './fonts/MyFont-Bold.woff2',    weight: '700', style: 'normal' },
    { path: './fonts/MyFont-Italic.woff2',  weight: '400', style: 'italic' },
  ],
  variable: '--font-my-font',
  display: 'swap',
})

Single file:

const myFont = localFont({
  src: './fonts/MyFont.woff2',
  display: 'swap',
})

Apply Font to Tailwind v4

/* app/globals.css */
@import "tailwindcss";

:root {
  --font-sans: var(--font-inter);
  --font-mono: var(--font-roboto-mono);
}

Gotchas

  • Font objects must be created in a separate file or at the module level — not inside a component body.
  • The className property applies the font directly; variable lets you use it in CSS/Tailwind.
  • For Tailwind v4, wire CSS variables in globals.css instead of tailwind.config.ts.