Lassen Sie uns eine völlig neue Website erstellen, die mit folgendem Tech-Stack betrieben wird:
Next.js 14 - Als modernes Web Framework für Frontend und Backend
App Router - Damit wir das Beste aus dem Project rausholen können und der Pages Router ist nicht mehr aktuell
Contentful - Unser headless CMS
Typescript - Typisiertes Javascript
Dies ist der erste Beitrag einer Reihe, in der wir eine Website von Grund auf erstellen werden. Zuerst beginnen wir mit der Projektinitialisierung, dann erstellen wir das Contentful-Konto und als letzten Schritt integrieren wir Contentful als Headless CMS in unser Next.js-Projekt. In den folgenden Beiträgen werden wir tiefer in das Projekt eindringen und Funktionen wie Mehrsprachigkeitsunterstützung, Benutzerregistrierung/-authentifizierung, erweiterte Suche mit Algolia und vieles mehr hinzufügen.
Alle verwendeten Services sind kostenlos und gut geeignet für kleinere Projekte.
Projekt erstellen mit create-next-app
Wir benutzen die "latest" Version des create-next-app pakets
npx create-next-app@latest
Ich verwende VS Code für die Entwicklung, also bitte installieren Sie VS Code https://code.visualstudio.com/download
Öffnen Sie VSCode und falls Sie einen Mac verwenden, dann Command + Shift + P, dies öffnet die Befehlspalette von VSCode, und tippen Sie nun „shell“ ein. Sie sollten „Shell-Befehl: Befehl 'Code' im Pfad installieren“ im Dropdown-Menü sehen. Bitte wählen Sie es aus und jetzt ist VSCode in Ihrem Pfad. So können Sie in Ihren zuvor erstellten Ordner springen und tippen
code .dieser Befehl öffent VSCode direkt im Projektverzeichnis. Jetzt register wir uns noch bei www.contentful.com und schon sind wir ready. Nach dem ersten Login sollten Sie „Von Grund auf neu starten“ auswählen.

Erstellen der Contentful API Token & Space ID
Jetzt erstellen wir die benötigten API-Schlüssel für unsere .env.local-Datei. Zuerst Space_ID, Access_Token und Preview_Access_Token und dann Management_Token für Schreib-/Einfügeoperationen.




Management Token (CMA)


Env File und Npm Packages
Erstellen wir nun die Datei .env.local für die Umgebungsvariablen im Projektverzeichnis
##.env.local##
CONTENTFUL_SPACE_ID=xxxx
CONTENTFUL_ACCESS_TOKEN=xxxx
CONTENTFUL_PREVIEW_ACCESS_TOKEN=xxxx
CONTENTFUL_MANAGEMENT_TOKEN=xxxx
CONTENTFUL_PREVIEW_SECRET=xxxxNpm pakete hinzufügen
npm install @graphql-codegen/cli graphql graphql-request
npm install @graphql-codegen/typescript-graphql-request @graphql-codegen/introspectionNun erstellen wir die Datei codegen.ts im Projektverzeichnis
##codegen.ts##
// Purpose: Configuration for GraphQL Code Generator
import { CodegenConfig } from "@graphql-codegen/cli";
const endpointOverride = process.env.CONTENTFUL_GRAPHQL_ENDPOINT;
const productionEndpoint = "https://graphql.contentful.com/content/v1/spaces";
export const endpoint = `${endpointOverride || productionEndpoint}/${
process.env.CONTENTFUL_SPACE_ID
}`;
export const config: CodegenConfig = {
overwrite: true,
ignoreNoDocuments: true,
schema: [
{
[endpoint || ""]: {
headers: {
Authorization: `Bearer ${process.env.CONTENTFUL_PREVIEW_ACCESS_TOKEN}`,
},
},
},
],
generates: {
"src/lib/__generated/graphql.schema.json": {
plugins: ["introspection"],
},
"src/lib/__generated/graphql.schema.graphql": {
plugins: ["schema-ast"],
},
"src/lib/__generated/sdk.ts": {
documents: ["src/lib/graphql/**/*.graphql"],
plugins: [
"typescript",
"typescript-operations",
"typescript-graphql-request",
],
config: {
rawRequest: false,
inlineFragmentTypes: "combine",
skipTypename: false,
exportFragmentSpreadSubTypes: true,
dedupeFragments: true,
preResolveTypes: true,
},
},
},
};
export default config;Wir müssen diese zwei Zeilen Code in der Datei package.json hinzufügen, damit später die Befehle funktionieren
##script section of package.json##
"graphql-codegen:generate": "graphql-codegen -r dotenv/config --config codegen.ts dotenv_config_path=.env.local",
"graphql-codegen:watch": "graphql-codegen --watch -r dotenv/config --config codegen.ts dotenv_config_path=.env.local"##package.json##
{
"name": "nextjs13_5-typescript-app-router-contentful",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"graphql-codegen:generate": "graphql-codegen -r dotenv/config --config codegen.ts dotenv_config_path=.env.local",
"graphql-codegen:watch": "graphql-codegen --watch -r dotenv/config --config codegen.ts dotenv_config_path=.env.local"
},
"dependencies": {
"@graphql-codegen/cli": "^5.0.2",
"@graphql-codegen/introspection": "^4.0.3",
"@graphql-codegen/typescript-graphql-request": "^6.2.0",
"graphql": "^16.8.1",
"graphql-request": "^6.1.0",
"next": "14.1.3",
"react": "^18",
"react-dom": "^18"
},
"devDependencies": {
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
"autoprefixer": "^10",
"eslint": "^8",
"eslint-config-next": "13.5.6",
"postcss": "^8",
"tailwindcss": "^3",
"typescript": "^5"
}
}Verzeichnisse und Dateien anlegen für GraphQL
Erstellen der Dateien src/lib und client.ts
##src/lib/client.ts##
import { GraphQLClient } from "graphql-request";
import { getSdk } from "@/lib/__generated/sdk";
import { endpoint } from "../../codegen";
const graphQlClient = new GraphQLClient(endpoint, {
headers: {
Authorization: `Bearer ${process.env.CONTENTFUL_PREVIEW_ACCESS_TOKEN}`,
},
});
export const client = getSdk(graphQlClient);Erstellen Sie einen Ordner „graphql“ unter src/lib/ und innerhalb des Ordners „graphql“ erstellen Sie diese .graphql-Dateien (Sie können sie vom Github-Repo bekommen)
##graphql files##
authorFields.graphql
imageFields.graphql
pageBlogPost.graphql
pageBlogPostCollection.graphql
richImageFields.graphql
seoFields.graphqlJetzt erstellen wir einen neuen Ordner namens contentfulsync im Projektstammverzeichnis und fügen dann diese Zeilen im Skriptbereich der package.json hinzu
npm install contentful-cliLassen Sie uns die Importkonfigurationsdatei für die contentful-cli unter contentfulsync/import/config/contentful-import-config.json erstellen
##contentfulsync/import/config/contentful-import-config.json##
{
"contentFile": "./contentfulexport/import/export.json"
}Neues Verzeichnis erstellen contentfulsync/export/config
##contentfulsync/export/config/contentful-import-config.json##
{
"exportDir": "contentfulsync",
"contentFile": "export.json",
"downloadAssets": false
}Daten in den Contentful Space importieren
Jetzt können wir den Import durchführen
npm run cf-importNachdem dies erledigt ist, sind die Inhaltstypen und der Inhalt in unserem Contentful Space vorhanden.
Und das Frontend ?
Um die Daten im Frontend anzeigen zu können, müssen wir fehlende npm-Pakete installieren.
npm install @contentful/rich-text-react-renderer tailwind-mergeAls nächster Schritt fügen wir diese Komponenten unter src/components hinzu (erstellen Sie den Komponentenordner, falls er nicht existiert)
##Components##
ArticleContent.component.tsx
ArticleImage.component.tsx
CtfImage.component.tsx
CtfRichText.component.tsxJetzt noch die Datei page.tsx im Verzeichnis src/app/ anpassen
import { ArticleContent } from "@/components/contentful/ArticleContent.component";
import { client } from "@/lib/client";
import { notFound } from "next/navigation";
async function BlogPostPage() {
const [blogPagedata] = await Promise.all([
client.pageBlogPost({
slug: "testblogpost",
}),
]);
const blogPost = blogPagedata.pageBlogPostCollection?.items[0];
if (!blogPost) {
// If a blog post can't be found,
// tell Next.js to render a 404 page.
return notFound();
}
const relatedPosts = blogPost?.relatedBlogPostsCollection?.items;
if (!blogPost || !relatedPosts) return null;
return (
<>
{/* <Container className="max-w-4xl mt-8"> */}
<div className="mt-4" />
<ArticleContent article={blogPost} />
{/* </Container> */}
</>
);
}
export default BlogPostPage;Deployment
Dev Server starten
npm run devführt zu einem Fehler, da die Domain, von der die Bilder bereitgestellt wurden „images.ctfassets.net“, nicht konfiguriert ist. Gehen wir also zu unserer next.config.js Datei und ändern sie, sodass sie folgendermaßen aussieht:
/** @type {import('next').NextConfig} */
const nextConfig = {
images: { domains: ["images.ctfassets.net"] },
reactStrictMode: true,
};
module.exports = nextConfig;Nun sollte der Entwicklungsserver starten und wir können die URL http://localhost:3000 verwenden, um das Ergebnis zu sehen.

Das war's. Die Grundlagen sind geschaffen und im nächsten Beitrag werden wir mit dem Frontend fortfahren, dann wie wir zusätzliche Sprachen handhaben können, Benutzerregistrierung/-anmeldung und vieles mehr. Bleiben Sie gespannt und natürlich dran.
Github Repo
https://github.com/cloudapp-dev/nextjs13_5-typescript-app-router-contentful
Wenn Ihnen gefällt, was Sie sehen, dann unterstützen Sie mich bitte mit einem "Clap" oder folgen Sie mir auf medium.com.



