evo sta kaze gemini:
Ovaj problem je specifičan za Next.js App Router i najčešće je povezan s načinom na koji Next.js rukuje streamingom i ISR (Incremental Static Regeneration) cacheom na self-hosted okruženjima.
Problem “Untitled” se javlja jer Next.js renderira prije nego što su podaci za generateMetadata potpuno spremni ili kada dođe do tihe pogreške tijekom revalidacije.
Evo konkretnih uzroka i rješenja:
- Problem sa Suspense i Redoslijedom Streaminga
U App Routeru, Next.js pokušava streamati HTML čim prije. Ako vaš layout.tsx ili page.tsx ima Suspense granicu, a metapodaci ovise o istom fetch pozivu koji je “usporen” ili se revalidira, Next.js ponekad izbaci inicijalni shell s defaultnim (ili praznim) naslovom dok čeka podatke.
Rješenje:
Osigurajte da generateMetadata koristi istu memoiziranu funkciju kao i sama stranica. Next.js automatski radi fetch deduplication.
// Koristite React 'cache' za funkcije koje nisu 'fetch' (npr. GraphQL klijent)
import { cache } from 'react'
const getPost = cache(async (slug) => {
return await sdk.getPost(slug)
})
export async function generateMetadata({ params }) {
try {
const post = await getPost(params.slug)
if (!post) return { title: 'Post Not Found' }
return { title: post.title }
} catch (e) {
return { title: 'Default Title' } // Uvijek imajte fallback
}
}
- ISR / Revalidation Race Condition (Najvjerojatniji uzrok)
Budući da koristite WordPress i ISR, problem se javlja nakon objave članka. Kada stigne zahtjev za revalidaciju, Next.js u pozadini pokušava generirati novu stranicu. Ako WPGraphQL u tom milisekundu vrati prazan odgovor ili 404 (dok se WP cache ne osvježi), Next.js može keširati “prazne” metapodatke.
Zašto vidite “Untitled”?
Ako generateMetadata baci error koji nije uhvaćen, ili vrati undefined, Next.js ponekad (ovisno o verziji) fallbacka na interni default “Untitled” umjesto da sruši stranicu.
Rješenje:
Provjerite stale-while-revalidate logiku: Na vlastitom VPS-u, provjerite imate li dovoljno RAM-a. PM2 zna ubiti proces tijekom teškog next build ili revalidacije, što ostavlja proces u međustanju.
Hardkodirani fallback u Root Layoutu: Osigurajte da layout.tsx ima definiran title u metadata objektu. On bi trebao služiti kao baza.
- Problem s “Host” Headerom (Self-hosted specifičnost)
Next.js metapodaci ponekad interno trebaju znati metadataBase. Ako nije definirana, generiranje apsolutnih URL-ova (za OG slike i sl.) može tiho zakazati i poremetiti renderiranje heada.
Rješenje:
Dodajte metadataBase u vaš layout.tsx:
export const metadata = {
metadataBase: new URL('https://vasadomena.com'),
title: {
default: 'Moj Brand',
template: '%s | Moj Brand',
},
}
- Kako debugirati na VPS-u (Trajno rješenje)
Budući da se problem javlja nakon objave u WordPressu, provjerite sljedeće:
WPGraphQL Cache: Ako koristite plugin poput WPGraphQL Smart Cache, on može vratiti stari null rezultat dok se cache ne regenerira.
Next.js verzija: Ako ste na verziji 13.x ili ranoj 14.x, preporuka je nadogradnja na posljednju stabilnu verziju (14.2+ ili 15). Bilo je mnogo ispravaka vezanih uz “metadata streaming race conditions”.
Logs: Umjesto običnog loga, dodajte console.error unutar generateMetadata catch bloka i gledajte PM2 logove (pm2 logs). Ako vidite “fetch error” u trenutku kad se pojavi “Untitled”, znate da je do komunikacije s WordPressom.
Sažetak koraka:
Koristite React.cache za GraphQL pozive kako bi generateMetadata i Page dijelili isti podatak.
Postavite metadataBase u root layout.
U generateMetadata obavezno koristite try-catch koji vraća objekt s naslovom čak i ako fetch ne uspije.
Ažurirajte Next.js (često rješava čudne App Router bugove s head tagovima).