JSTAcademy
0 XP
Dashboard
Crash Courses
Image, Font & Metadata Optimization
10 min
Masters+175 XP
Crash Courses · Masters

Image, Font & Metadata Optimization

Optimize Core Web Vitals with next/image, next/font, and the Metadata API.
10 min read+175 XP on completionCert: Next.js Crash Course
Tap any word in the text below to start reading from there.

Image, Font & Metadata Optimization

Three of the biggest Core Web Vitals killers are images, fonts, and missing metadata. Next.js has built-in solutions for all three.

next/image — Automatic Optimization

import Image from 'next/image'

// Fixed-size — avatar, logo, icon
<Image
  src="/logo.png"
  alt="JST Academy"
  width={120}
  height={40}
  priority  // LCP image — skip lazy loading, load immediately
/>

// Responsive — hero, card cover
<div className="relative h-64">
  <Image
    src="/hero.jpg"
    alt="Academy Hero"
    fill                         // fills the parent container
    className="object-cover"
    sizes="(max-width: 768px) 100vw, 50vw"  // hints for responsive sizing
    priority
  />
</div>

What next/image does automatically:

  • Converts images to WebP or AVIF (smaller file sizes)
  • Applies lazy loading unless priority is set
  • Reserves the correct space before the image loads (prevents CLS)
  • Generates a blur placeholder for progressive loading (with placeholder="blur")
  • Generates responsive sizes via srcset for the sizes prop

For fill images, the parent must have position: relative.

next/font — Zero-Shift Fonts

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

const inter = Inter({
  subsets: ['latin'],
  variable: '--font-inter',   // CSS variable for Tailwind
})

const playfair = Playfair_Display({
  subsets: ['latin'],
  variable: '--font-playfair',
  weight: ['400', '700'],
})

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

next/font downloads fonts at build time and hosts them on your domain. No external Google Fonts DNS request at runtime, no layout shift when fonts swap in, and no user tracking by Google (GDPR-friendly).

Metadata API — SEO and Social Tags

// app/layout.tsx — static metadata (applies to all pages via template)
import type { Metadata } from 'next'

export const metadata: Metadata = {
  title: {
    template: '%s | JST Academy',   // page titles become "React Course | JST Academy"
    default: 'JST Academy',
  },
  description: 'PhD-level crash courses for modern web developers.',
  openGraph: {
    images: [{ url: '/og-image.jpg', width: 1200, height: 630 }],
    siteName: 'JST Academy',
  },
  twitter: {
    card: 'summary_large_image',
  },
}
// app/courses/[id]/page.tsx — dynamic metadata from route params
export async function generateMetadata({
  params
}: {
  params: Promise<{ id: string }>
}): Promise<Metadata> {
  const { id } = await params
  const course = await getCourse(id)

  if (!course) return { title: 'Not Found' }

  return {
    title: course.title,             // becomes "React Crash Course | JST Academy"
    description: course.moduleObjective,
    openGraph: {
      title: course.title,
      description: course.moduleObjective,
      images: [{ url: `/og/${id}.jpg`, width: 1200, height: 630 }],
    },
  }
}

Verifying Your Optimization

Test your pages with:

  • Google PageSpeed Insights — real-world Core Web Vitals scores
  • Chrome DevTools Network tab — verify images serve WebP format
  • Twitter Card Validator / Facebook Debugger — verify OG tags render correctly on social
0%