Gehen wir davon aus, dass Sie planen, eine On-Page-Suche auf Ihrer Website oder Ihrem Blog zu integrieren und Sie wissen nicht, welche Lösung einfach zu implementieren und dazu auch noch kostenlos ist. Haben Sie bereits von dem Headless CMS Contentful und der KI-Suche Algolia gehört?
Wir bereits in meinen vorherigen Artikeln beschrieben (Schritt-für-Schritt Anleitung für das ganze Projekt -> Next js Content Management, Quo Vadis ? ) gibt es großzügige Abomodelle von Contentful und Algolia.
Algolia — Build Plan (Kostenlos)
Bis zu 10k Suchanfragen pro Monat
1 Mio. Datensätze
KI Funktionen stehen zum Testen bereit
Contentful — Free Plan
5 Benutzer
2 Sprachen
1M API Anfragen / Monat
Community-support
Strukturierter Inhalt
Entwickler tools
1 Intro Space
Next.js 14 — Route
Native Api Funktionen von Next.js
Beginnen wir damit, ein neues Contentful-Konto zu registrieren (falls noch nicht geschehen). Hier sind zwei Beiträge mit einer Schritt-für-Schritt-Anleitung:
Contentful Kontoregistrierung
Nextjs 13.5.6 — Complete Example — Typescript / App Router / Contentful and a lot more
Weitere Informationen zu den Inhaltstypen und GraphQL
Next.js 14 — Complete Example — Typescript / Tailwindcss / Contentful — Part 2
Jetzt noch ein Algolia Konto registrieren
Sign Up for an Algolia account
Sie können den sog. Social Login verwenden oder Ihre Mailadresse. Nachdem Sie angemeldet sind, müssen Sie eine Anwendung erstellen (Algolia erstellt nach der ersten Anmeldung eine Standardanwendung). Klicken Sie zunächst auf (1), um die Einstellungsseite zu öffnen, und dann auf (2), um die Übersichtsseite der Anwendung zu öffnen.

Hier sieht man die Übersichtsseite der Anwendungen ohne einen Index (1).

Klicken wir auf (2), um die Übersichtsseite der Suche zu öffnen, und dann klicken wir auf den Button „Index erstellen“. Wir werden ihn „example_dev“ nennen.


Gehen wir jetzt zurück zur Übersichtsseite der Einstellungen (unteres linkes Symbol -> wie im ersten Algolia-Screenshot gezeigt), aber jetzt klicken wir im linken Abschnitt „Team und Zugriff“ auf „API-Schlüssel“. Wir gelangen auf die Übersichtsseite der API-Schlüssel, wo wir drei Werte benötigen (“Application ID”, “Search-Only API Key” and ”Admin API Key”). Der Search-Only-Schlüssel wird im nächsten Beitrag verwendet, während der Frontend-Implementierung von Algolia. Jetzt benötigen wir den Admin-API-Schlüssel, weil wir Daten in den zuvor erstellten Index „example_dev“ schreiben müssen.

Nachdem beide Accounts (Contentful und Algolia) registriert und konfiguriert wurden, erstellen wir mit Next.js 14 den Api Endpunkt für den Daten-Push Richtung Algolia.
Sie können auch direkt das unten angeführte GitHub-Repository klonen.
GitHub link -> GitHub - cloudapp-dev/nextjs14-SEO
welches bereits den kompletten Code der 6 vorhergehenden Artikel beinhaltet (Übersicht) + SEO Zusatzinfos
Wir fügen folgenden Variablen zur Datei .env.local hinzu
NEXT_PUBLIC_ALGOLIA_APP_ID=xxxx -> Algolia ApplicationID
NEXT_PUBLIC_ALGOLIA_API_KEY=xxxx -> Algolia Search-Only Key used later
ALGOLIA_MASTER_KEY=xxxx -> Algolia Admin Key (Write rights)
NEXT_PUBLIC_ALGOLIA_INDEX_NAME=example_dev
API_KEY=xxxxx -> Random Key, which we use for securing the endpointMit diesen Befehl können Sie einen Api-Key generieren.
node -e "console.log(crypto.randomBytes(32).toString('hex'))"Einen Endpunkt in Next.js erstellen
Für den neuen Endpunkt erstellen wir einen neuen Ordner unter /src/app/api mit dem Namen “algoliasync” mit der unten angeführten route.ts Datei darin.
import { NextRequest, NextResponse } from "next/server";
import { documentToPlainTextString } from "@contentful/rich-text-plain-text-renderer";
import { client } from "@/lib/client";
import { fallbackLng, locales } from "@/app/i18n/settings";
const apikey = process.env.API_KEY;
export async function POST(request: NextRequest) {
const document = await request.json();
let json_de: string = "";
let json_en: string = "";
if (request.headers.get("x-api-key") !== apikey) {
return new NextResponse(
JSON.stringify({ status: "fail", message: "You are not authorized" }),
{ status: 401 }
);
}
const locale = fallbackLng as string;
const blogPagedata = await client.pageBlogPost({
locale,
preview: false,
slug: document.slug,
});
const blogPost = blogPagedata.pageBlogPostCollection?.items[0];
json_en = documentToPlainTextString(blogPost.content?.json);
const tags = blogPost.contentfulMetadata?.tags;
const tagsnew: any = [];
tags.map((tag) => {
tagsnew.push(tag.id);
});
const blogPagedata_de = await client.pageBlogPost({
locale: "de-DE",
preview: false,
slug: document.slug,
});
const blogPost_de = blogPagedata_de.pageBlogPostCollection?.items[0];
json_de = documentToPlainTextString(blogPost_de.content?.json);
const AlgoliaUrl =
"https://" +
process.env.NEXT_PUBLIC_ALGOLIA_APP_ID +
".algolia.net/1/indexes/" +
process.env.NEXT_PUBLIC_ALGOLIA_INDEX_NAME +
"/" +
document.entityId;
const date = blogPost.publishedDate;
const formatDate = new Date(date).toISOString().substring(0, 10);
const timeStamp = new Date(date).getTime() / 1000;
const jsonData: any = {
entityId: document.entityId,
height: blogPost?.featuredImage?.height.toString(),
width: blogPost?.featuredImage?.width.toString(),
image: blogPost?.featuredImage?.url,
intName: document.intName,
lang: {
"de-DE": {
content: json_de,
shortDescription: document.shortDescription_de,
title: document.title_de,
},
"en-US": {
content: json_en,
shortDescription: document.shortDescription_en,
title: document.title_en,
},
},
pubdate: formatDate,
pubdatetimestamp: timeStamp,
slug: document.slug,
spaceId: document.spaceId,
tags: tagsnew,
};
const res = await fetch(AlgoliaUrl, {
method: "PUT",
body: JSON.stringify(jsonData),
headers: {
"Content-Type": "application/json; charset=utf-8",
"X-Algolia-API-Key": process.env.ALGOLIA_MASTER_KEY,
"X-Algolia-Application-Id": process.env.NEXT_PUBLIC_ALGOLIA_APP_ID,
},
});
if (!res.ok) {
const text = await res.text();
throw new Error(`
Failed to fetch data
Status: ${res.status}
Response: ${text}
`);
}
const result: any = await res.json();
// console.log("result", result);
return NextResponse.json(
{ transformed: true, date: Date.now() },
{ status: 200 }
);
}Am Dateianfang importieren wir diese NPM-Pakete
import { NextRequest, NextResponse } from "next/server"; -> standard Nextjs Api package
import { documentToPlainTextString } from "@contentful/rich-text-plain-text-renderer"; -> needed to extract the text part out of the JSON (Contentful Rich Text field)
import { client } from "@/lib/client"; -> client for Contentful graphQL operations
import { fallbackLng, locales } from "@/app/i18n/settings"; -> Language settingsDann kontrollieren wir auf die Richtigkeit des API Keys.
const apikey = process.env.API_KEY; -> getting API Key
// Return 401 in case we provide the wrong "x-api-key" in the header
if (request.headers.get("x-api-key") !== apikey) {
return new NextResponse(
JSON.stringify({ status: "fail", message: "You are not authorized" }),
{ status: 401 }
);
}Erstellen einen Contentful Webhook
Der letzte Schritt besteht darin, den neuen Webhook in Contentful einzurichten, sodass wir Änderungen/Löschungen an den neu erstellten Index „example_dev“ weiterleiten.


Hier eine Detailübersicht hinsichtlich der Erstellung des Webhook, welcher die Daten von Contentful über unseren Endpunkt, Richtung Algolia pushen wird.

der zweite Screenshot zeigt den zweiten Webhook für das sog. "unpublish" der Daten. Wenn ein Datensatz in Contentful gelöscht oder auf "unpublish" gesetzt wird, dann muss dies ebenfalls an Algolia übermittelt werden.

In diesem Tutorial habe ich das Projekt, das ich in den vorherigen Schritten erstellt habe, als Grundlage verwendet und daraufhin die Synchronisation zwischen Contentful und Algolia aufgebaut.
Cloudapp-dev und bevor Sie uns verlassen
Danke, dass Sie bis zum Ende gelesen haben. Noch eine Bitte bevor Sie gehen:
Wenn Ihnen gefallen hat was Sie gelesen haben oder wenn es Ihnen sogar geholfen hat, dann würden wir uns über einen "Clap" 👏 oder einen neuen Follower auf unseren Medium Account sehr freuen.






