Bug: Static metadata (export const metadata
) rendered in <body>
instead of <head>
in Next.js 15.5.4
This repository demonstrates a critical bug in Next.js 15.5.4 where metadata defined using export const metadata
is incorrectly injected into the <body>
tag instead of the <head>
tag.
This breaks:
- SEO (Search Engine Optimization)
- Open Graph sharing (Facebook, LinkedIn, WhatsApp)
- Twitter Cards
- HTML5 validation
npm install
npm run dev
- Navigate to http://localhost:3000
- Open DevTools (F12)
- Inspect the HTML source
- Search for
<title>
,og:title
,fb:app_id
, ortwitter:card
Expected: All metadata tags should be in <head>
Actual: All metadata tags are rendered in <body>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Only basic Next.js meta tags -->
</head>
<body>
<!-- ❌ WRONG: All custom metadata appears here -->
<title>Test App</title>
<meta name="description" content="Testing metadata bug in Next.js 15.5.4">
<meta property="og:title" content="Test App">
<meta property="fb:app_id" content="123456789">
<meta name="twitter:card" content="summary_large_image">
<!-- etc. -->
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- ✅ CORRECT: All custom metadata should be here -->
<title>Test App</title>
<meta name="description" content="Testing metadata bug in Next.js 15.5.4">
<meta property="og:title" content="Test App">
<meta property="fb:app_id" content="123456789">
<meta name="twitter:card" content="summary_large_image">
<!-- etc. -->
</head>
<body>
<!-- Page content -->
</body>
</html>
The bug occurs with this standard Next.js App Router code:
app/layout.tsx:
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: 'Test App',
description: 'Testing metadata bug in Next.js 15.5.4',
keywords: ['test', 'nextjs', 'bug'],
openGraph: {
type: 'website',
locale: 'en_US',
url: 'https://example.com',
siteName: 'Test App',
title: 'Test App',
description: 'Testing metadata bug',
images: [
{
url: '/og-image.jpg',
width: 1200,
height: 630,
alt: 'Test Image',
},
],
},
facebook: {
appId: '123456789',
},
twitter: {
card: 'summary_large_image',
title: 'Test App',
description: 'Testing metadata bug',
images: ['/twitter-image.jpg'],
},
}
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<head />
<body>{children}</body>
</html>
)
}
Next.js: 15.5.4
React: 19.2.0
Node: 20.x
Downgrade to Next.js 15.2.4:
{
"dependencies": {
"next": "15.2.4",
"react": "19.2.0",
"react-dom": "19.2.0"
}
}
Then:
rm -rf node_modules package-lock.json
npm install
npm run dev
This bug has severe consequences:
- Open Graph broken: Facebook, LinkedIn, WhatsApp ignore meta tags in
<body>
- Twitter Cards broken: Twitter expects meta tags in
<head>
- SEO issues: Search engines may not properly parse metadata from
<body>
- HTML validation fails: Meta tags in
<body>
violate W3C standards
- Vercel/Next.js Issue #XXXXX (to be created)
MIT