Using nextjs + contentful
Why I chose Contentful CMS
I created my first portfolio and blog site using Gatsbyjs, creating markdown files in the project and importing them into GraphQL for display.
When I planned to create a new version of my portfolio website this year, I wondered if I should manage all the markdowns in the project repo, so I looked for a CMS (Content Management System) and chose Contentful.
This time, I decided to try next.js and started my journey...
Start with the token
I won't write down what you need to do in the contenful dashboard, it's pretty intuitive, just do what it says.
After that, I added the tokens to .env.local. Preview is a feature that allows you to see your changes live on the website as you write content, but I didn't add it because I didn't see a need for it.
CONTENTFUL_SPACE_ID=YOUR_SPACE_ID
CONTENTFUL_ACCESS_TOKEN=YOUR_ACCESS_TOKEN
CONTENTFUL_PREVIEW_ACCESS_TOKEN=YOUR_PREVIEW_TOKEN
At first, I used the SDK
library provided in the SDK, but it worked locally but not in the environment after deploying to cloudflare pages.
I couldn't find the cause, so I gave up and later changed to the REST API... It was simple to use.
npm i contenful
// utils/contentful.ts
import { createClient } from 'contentful';
const client = createClient({
space: process.env.CONTENTFUL_SPACE_ID,
accessToken: process.env.CONTENTFUL_ACCESS_TOKEN,
})
// fetch blog posts
export const getBlogPosts = async () => {
const results = await client.getEntries({
content_type: 'blogPost', // content type created in the dashboard
})
return response.items
}
Using the REST API
// utils/contentful.ts
const CONTENTFUL_SPACE_ID = process.env.CONTENTFUL_SPACE_ID!;
const CONTENTFUL_ACCESS_TOKEN = process.env.CONTENTFUL_ACCESS_TOKEN!;
export async function fetchPosts() {
const url = `https://cdn.contentful.com/spaces/${CONTENTFUL_SPACE_ID}/environments/master/entries?access_token=${CONTENTFUL_ACCESS_TOKEN}&content_type=blogPost`;
const response = await fetch(url, {
headers: {
Authorization: `Bearer ${CONTENTFUL_ACCESS_TOKEN}`,
},
});
if (!response.ok) {
throw new Error(`Failed to fetch posts: ${response.statusText}`);
}
const data = await response.json();
return data;
}
export async function fetchPostBySlug(slug: string) {
const url = `https://cdn.contentful.com/spaces/${CONTENTFUL_SPACE_ID}/environments/master/entries?access_token=${CONTENTFUL_ACCESS_TOKEN}&content_type=blogPost&fields.slug=${slug}`;
const response = await fetch(url, {
headers: {
Authorization: `Bearer ${process.env.CONTENTFUL_ACCESS_TOKEN}`,
},
});
if (!response.ok) {
throw new Error(`Failed to fetch post: ${response.statusText}`);
}
const data = await response.json();
const post = data.items[0];
if (!post) {
throw new Error("Post not found");
}
return post;
}
Calling from a page
If you are using Next.js 13 and app router, you can fetch data like below.
const Blog: React.FC = async () => {
const posts = await fetchPosts();
...