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 },
}
}Reading progress
0% read
In this module
next/image
next/font
Metadata API
sizes prop
0%