Nitro CMS Headless Konzept
Im Headless-Setup ist Nitro CMS der Content-Layer. Damit jede Route ein konsistentes Layout und eine Navigation hat, wird als erstes immer die Config geladen. Erst danach wird entschieden, ob es sich um eine App-Route, eine CMS-Page oder eine Entity-Detailseite handelt.
Abfrage-Zyklus
Der Ablauf startet bei jeder Anfrage gleich: URL rein, Config holen, dann die Route klassifizieren. Die Config ist die Basis fuer Layout, Navigation und globale Inhalte. Ohne sie kannst du weder eine normale Seite noch eine Fehlerseite sauber im gleichen Rahmen rendern.
Wenn die Route als CMS-Page erkannt wird, wird zuerst geprueft, ob die URL in config.pages existiert. Nur dann wird die Page ueber das Pages Endpoint geladen. Das verhindert, dass Wildcard-Routen versehentlich beliebige URLs rendern.
Wenn die Route als Entity-Detail erkannt wird, laedst du das Entity Detail ueber das Entities Endpoint, typischerweise per bySlug oder per byEntityId. Existiert das Entity nicht, landet der Flow in der gleichen 404-Logik.
Wichtig: Ein 404 ist keine Sonderbehandlung ohne Layout, sondern eine normale Seite innerhalb des Layouts. Darum ist die Config auch fuer Fehlerfaelle immer der erste Schritt.
Diagramm
Wie du das in der Praxis umsetzt
Du brauchst im Frontend eine zentrale Stelle, die diesen Zyklus abarbeitet. Das kann ein SSR-Handler sein oder eine Client-seitige Navigation. Der technische Modus spielt keine Rolle, entscheidend ist die Reihenfolge.
Die URL-Klassifizierung sollte so gebaut sein, dass App-Routen und Entity-Detail-Routen vor einer CMS-Wildcard ausgewertet werden. Das vermeidet, dass die CMS-Logik Dinge uebernimmt, die eigentlich nicht aus Nitro kommen sollen.
Beim Rendering selbst gilt: Layout und Navigation kommen aus der Config, der eigentliche Seiteninhalt kommt entweder aus der Page Payload oder aus dem Entity Detail Payload. Dadurch bleibt die Seite konsistent, auch wenn der Content-Typ wechselt.
Minimaler Pseudocode
async function handleRequest(path: string) {
const config = await nitro.getConfig()
const routeType = classifyRoute(path) // "app" | "page" | "entity"
if (routeType === "app") {
return renderApp({ config, path })
}
if (routeType === "entity") {
const { type, key } = parseEntityRoute(path) // key = slug oder id
const entity = await nitro.getEntityDetail({ type, key })
if (!entity) return render404({ config })
return renderEntity({ config, entity })
}
// routeType === "page"
if (!config.pages.includes(path)) {
return render404({ config })
}
const page = await nitro.getPage({ path })
if (!page) return render404({ config })
return renderPage({ config, page })
}
