Deine Artikel in deinem Next.js-Blog.
makeseo schreibt und terminiert die Beiträge, dein Blog holt sie serverseitig über einen privaten API-Schlüssel und rendert sie in deinem eigenen Layout. Kein Webhook, kein Deployment je Beitrag.
Du brauchst ein Next.js-Projekt mit App Router und zehn Minuten. Nicht technisch? Der gehostete Blog kommt ganz ohne Code aus.
Serverseitig
Dein Blog fragt unsere API auf dem Server ab. Der Schlüssel steht in einer Umgebungsvariablen und erreicht den Browser nie.
Statisch und aktuell
Jede Seite ist vorgerendert und erneuert sich alle 10 Minuten (ISR). Neue Beiträge erscheinen ohne Deployment.
Läuft überall
Vercel, Netlify, Cloudflare, eigener Node-Server. Keine Abhängigkeit ausser fetch, keine Datenbank auf deiner Seite.
1 · Integration erstellen & Schlüssel kopieren
In makeseo: Einstellungen › Integrationen → Kachel Next.js Blog. Trage die Adresse ein, unter der dein Blog später liegt (z. B. https://deine-domain.de/blog) und klicke Integration erstellen.
Die eingetragene Adresse entscheidet, welche URL makeseo an einem veröffentlichten Beitrag hinterlegt. Sie sollte stimmen, bevor der erste Beitrag live geht.
2 · npm-Paket installieren
Der Client ist ein kleines TypeScript-Modul ohne Abhängigkeiten:
npm install @makeseo/blog3 · app/blog-Starter kopieren
Kopiere den Ordner app/blog aus dem Starter in dein App-Router-Projekt. Damit hast du sofort vier Routen:
app/blog/
page.tsx Übersicht → /blog
[slug]/page.tsx Beitrag → /blog/mein-beitrag
tag/[slug]/page.tsx Themenseite → /blog/tag/ki-sichtbarkeit
sitemap.xml/route.ts Sitemap → /blog/sitemap.xml
_lib/client.ts der eine Zugang zu makeseo
_lib/makeseo.ts eingebetteter Client (entfällt mit dem npm-Paket)
_lib/article-styles.tsx Stylesheet + ArtikelkörperMit installiertem Paket ersetzt du den Inhalt von _lib/client.ts durch:
import { createMakeseoClient } from "@makeseo/blog";
export const makeseo = createMakeseoClient({ revalidate: 600 });
export type { MakeseoPost, MakeseoPostSummary, MakeseoTag, MakeseoTheme } from "@makeseo/blog";Willst du gar nichts kopieren, reichen diese Zeilen für eine eigene Beitragsseite:
import { notFound } from "next/navigation";
import { createMakeseoClient } from "@makeseo/blog";
const makeseo = createMakeseoClient();
export const revalidate = 600;
export default async function Post({
params,
}: {
params: Promise<{ slug: string }>;
}) {
const { slug } = await params;
const [post, { theme }] = await Promise.all([
makeseo.getPost(slug),
makeseo.getTheme(),
]);
if (!post) notFound();
return (
<main>
<style dangerouslySetInnerHTML={{ __html: theme.stylesheet }} />
<h1>{post.title}</h1>
<div
className="ms-article"
dangerouslySetInnerHTML={{ __html: post.contentHtml }}
/>
</main>
);
}4 · Umgebungsvariable setzen
MAKESEO_BLOG_API_KEY=msk_live_dein_schluessel
NEXT_PUBLIC_SITE_URL=https://deine-domain.deDieselben Variablen gehören in die Umgebungsvariablen deines Deployments. Fehlen sie dort, läuft nur die lokale Entwicklung — und der Fehler sieht so aus, als sei der Schlüssel falsch.
5 · Externe Bild-Hosts erlauben
Beitragsbilder und Infografiken liegen nicht auf deiner Domain. next/image lädt nur von ausdrücklich erlaubten Hosts:
import type { NextConfig } from "next";
const config: NextConfig = {
images: {
remotePatterns: [
// Stockfotos
{ protocol: "https", hostname: "images.pexels.com" },
// Beitragsbilder und Infografiken aus makeseo
{ protocol: "https", hostname: "*.supabase.co" },
],
},
};
export default config;Ohne diesen Eintrag bricht der Build mit hostname is not configured under images ab.
6 · Blog starten und /blog öffnen
npm run devÖffne http://localhost:3000/blog. Du solltest deine veröffentlichten Beiträge sehen. Kommt eine leere Liste, ist vermutlich noch keiner veröffentlicht — Entwürfe liefert die API bewusst nicht aus.
7 · Sitemap in der Search Console einreichen
Nach dem Deployment: Google Search Console → Sitemaps → eintragen:
blog/sitemap.xmlEine eigene Sitemap für den Blog hat einen praktischen Vorteil: du siehst in der Search Console getrennt, wie viele Beiträge indexiert sind.
Cache und Aktualisierung
Jede Blogseite ist statisch und erneuert sich per ISR alle 600 Sekunden. Ein in makeseo veröffentlichter Beitrag erscheint also spätestens nach dieser Zeit — ohne Deployment, ohne Webhook.
Beiträge, die nach dem Build erscheinen, funktionieren trotzdem: generateStaticParams erzeugt die bekannten Seiten vorab, der Rest entsteht beim ersten Aufruf.
Was synchronisiert wird
- Titel und Slug
- Meta-Titel und Meta-Beschreibung
- Artikelkörper als fertiges HTML — und dieselbe Fassung als Markdown
- Beitragsbild
- Tags (Label und Slug) für deine Themenseiten
- Lesezeit und Wortzahl
- Sprache des Beitrags
- Zeitstempel: publishedAt und updatedAt
Das HTML ist Zeichen für Zeichen dasselbe, das du in der Vorschau im Dashboard siehst. Es gibt keinen zweiten Renderer.
Deine Markenfarbe kommt automatisch mit
Beim Analysieren deiner Website erkennt makeseo deine Markenfarbe. Sie wird automatisch auf die eingebetteten Links im Artikel angewendet — du musst nichts einstellen. Der Fliesstext bleibt schwarz auf weiss; gefärbt wird nur, was anklickbar ist.
Geliefert wird das über /api/blog/v1/theme: das fertige Stylesheet (gescoped auf .ms-article, es kann dein Theme nicht verändern) und zusätzlich der reine Farbwert als linkColor, falls du dein eigenes CSS mitbringst.
const { theme } = await makeseo.getTheme();
<div
className="ms-article"
style={
theme.linkColor
? ({ "--ms-a-link": theme.linkColor } as React.CSSProperties)
: undefined
}
dangerouslySetInnerHTML={{ __html: post.contentHtml }}
/>Wurde für dein Projekt keine Marke erkannt, ist linkColor gleich null und die Links bleiben schwarz. Es wird nie eine Farbe geraten. Überschreiben kannst du sie in makeseo unter Einstellungen › Integrationen.
Die API im Detail
Basis: https://app.makeseo.co/api/blog/v1. Jede Anfrage braucht den Header Authorization: Bearer <MAKESEO_BLOG_API_KEY>. Der Schlüssel gehört nie in eine URL — Adressen landen in Logs, Header nicht.
GET /api/blog/v1/posts?page=1&limit=12&tag=ki-sichtbarkeit
→ { posts, page, pageSize, total, totalPages }
GET /api/blog/v1/posts/<slug>
→ { post } (404, wenn es ihn nicht veröffentlicht gibt)
GET /api/blog/v1/tags
→ { tags: [{ label, slug, count }] }
GET /api/blog/v1/theme
→ { blogName, theme: { stylesheet, linkColor, className } }curl -H "Authorization: Bearer $MAKESEO_BLOG_API_KEY" \
https://app.makeseo.co/api/blog/v1/postsWenn etwas klemmt
Die Meldungen im Wortlaut, den die API zurückgibt — und was dahintersteckt.
- 401 missing_api_key
- Es kam kein Authorization-Header an. In neun von zehn Fällen ist die Variable nur lokal gesetzt und fehlt in den Umgebungsvariablen des Deployments — lokal läuft es dann, live nicht.
- 401 malformed_api_key
- Der Wert kam als leerer String oder als „undefined“ an. Prüfe die Schreibweise: MAKESEO_BLOG_API_KEY, ohne Präfix, ohne Anführungszeichen um den Wert.
- 403 revoked_api_key
- Der Schlüssel wurde ersetzt. Ein neu erzeugter zieht den bisherigen sofort zurück. Trage den neuen Wert ein und deploye neu.
- Die Beitragsliste ist leer.
- Die API liefert ausschliesslich veröffentlichte Beiträge. Entwürfe und terminierte Beiträge erscheinen erst zu ihrem Termin — den siehst du im Content-Plan.
- Ein neuer Beitrag erscheint nicht sofort.
- Das ist der ISR-Cache deiner Seite, kein Fehler. Bis zu 10 Minuten sind normal. Wer es schneller braucht, setzt revalidate herunter oder ruft revalidatePath("/blog") aus einer eigenen Route auf.
- Bilder laden nicht.
- next/image lädt nur von ausdrücklich erlaubten Hosts. Trage images.pexels.com und *.supabase.co in die remotePatterns deiner next.config.ts ein (Schritt 5).
Schick uns deine Fehlermeldung — wir schauen drauf.
Lieber ohne Code? Gehosteten Blog einrichten