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

Next.js ships built-in optimization for the three biggest CWV killers: images, fonts, and metadata.

next/image

import Image from 'next/image'

// Fixed-size image (avatar, logo)
<Image
  src="/logo.png"
  alt="JST Academy"
  width={120}
  height={40}
  priority  // LCP image — load eagerly
/>

// Responsive image (hero, card)
<Image
  src="/hero.jpg"
  alt="Hero"
  fill             // fills parent container
  className="object-cover"
  sizes="(max-width: 768px) 100vw, 50vw"
/>

The parent of a fill image needs position: relative.

next/font

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

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

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>
  )
}

Metadata API

// Static metadata
export const metadata: Metadata = {
  title: { template: '%s | JST Academy', default: 'JST Academy' },
  description: 'PhD-level crash courses.',
  openGraph: {
    images: [{ url: '/og-image.jpg', width: 1200, height: 630 }],
  },
}

// Dynamic metadata from params
export async function generateMetadata({ params }: Props): Promise<Metadata> {
  const course = await getCourse((await params).id)
  return {
    title: course?.title,
    description: course?.moduleObjective,
    openGraph: { title: course?.title },
  }
}
0%