Skip to content

Instantly share code, notes, and snippets.

@fabiconcept
Created August 11, 2025 11:33
Show Gist options
  • Save fabiconcept/8a7ceb40c27a86e7303caa0587d93183 to your computer and use it in GitHub Desktop.
Save fabiconcept/8a7ceb40c27a86e7303caa0587d93183 to your computer and use it in GitHub Desktop.
Contentful
import { createClient } from 'contentful';
if (!process.env.NEXT_PUBLIC_CONTENTFUL_SPACE_ID) throw new Error("Content space ID is missing!")
if (!process.env.NEXT_PUBLIC_CONTENTFUL_ACCESS_TOKEN) throw new Error("Content Access Token is missing!")
const client = createClient({
space: process.env.NEXT_PUBLIC_CONTENTFUL_SPACE_ID!,
accessToken: process.env.NEXT_PUBLIC_CONTENTFUL_ACCESS_TOKEN!,
});
export default client;
import client from './client';
import { NewsPost, Ministry } from './types';
class ContentfulService {
// Fetch all ministries
async getMinistries(): Promise<Ministry[]> {
try {
const response = await client.getEntries({
content_type: 'ministry',
order: ['fields.ministryName'],
});
return response.items as unknown as Ministry[];
} catch (error) {
console.error('Error fetching ministries:', error);
return [];
}
}
async getBlogsByMinistry(ministryId: string): Promise<NewsPost[]> {
try {
const response = await client.getEntries({
content_type: 'blogs',
'fields.ministry.sys.id': ministryId,
order: ['-sys.createdAt'],
include: 2,
});
return response.items as unknown as NewsPost[];
} catch (error) {
console.error('Error fetching blogs by ministry:', error);
return [];
}
}
async getBlogByMinistrySlug(slug: string): Promise<NewsPost | null> {
try {
const response = await client.getEntries({
content_type: 'blogs',
'fields.ministry.fields.slug': slug,
include: 2,
limit: 1,
});
return response.items[0] as unknown as NewsPost || null;
} catch (error) {
console.error('Error fetching blog by ministry slug:', error);
return null;
}
}
// Fetch all blogs
async getAllBlogs(): Promise<NewsPost[]> {
try {
const response = await client.getEntries({
content_type: 'blogs',
order: ['-sys.createdAt'],
include: 2, // Include linked entries (ministry, author)
});
return response.items as unknown as NewsPost[];
} catch (error) {
console.error('Error fetching all blogs:', error);
return [];
}
}
// Fetch a single blog post by slug
async getBlogBySlug(slug: string): Promise<NewsPost | null> {
try {
const response = await client.getEntries({
content_type: 'blogs',
'fields.slug': slug,
include: 2,
limit: 1,
});
return response.items[0] as unknown as NewsPost || null;
} catch (error) {
console.error('Error fetching blog by slug:', error);
return null;
}
}
// Fetch a ministry by slug
async getMinistryBySlug(slug: string): Promise<Ministry | null> {
try {
const response = await client.getEntries({
content_type: 'ministry',
'fields.slug': slug,
include: 2,
limit: 1,
});
return response.items[0] as unknown as Ministry || null;
} catch (error) {
console.error('Error fetching ministry by slug:', error);
return null;
}
}
async getMediaByMinistryId(id: string): Promise<NewsPost | null> {
try {
const response = await client.getEntries({
content_type: 'media',
'fields.ministry.sys.id': id,
include: 2,
limit: 1,
});
return response.items[0] as unknown as NewsPost || null;
} catch (error) {
console.error('Error fetching media by ministry id:', error);
return null;
}
}
}
// Export an instance to maintain the same usage pattern
export const contentfulService = new ContentfulService();
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
images: {
domains: ["images.ctfassets.net"],
},
};
export default nextConfig;
export interface Ministry {
sys: {
id: string;
type: string;
createdAt: string;
updatedAt: string;
};
fields: {
ministryName: string;
slug: string;
description?: string;
};
}
export interface Author {
sys: {
id: string;
type: string;
createdAt: string;
updatedAt: string;
};
fields: {
name: string;
bio?: string;
avatar?: {
sys: {
id: string;
type: string;
};
fields: {
title: string;
description?: string;
file: {
url: string;
fileName: string;
contentType: string;
};
};
};
};
}
export interface NewsPost {
sys: {
id: string;
type: string;
createdAt: string;
updatedAt: string;
};
fields: {
title: string;
slug: string;
featuredImage?: {
sys: {
id: string;
type: string;
};
fields: {
title: string;
description?: string;
file: {
url: string;
fileName: string;
contentType: string;
};
};
};
media?: Array<{
sys: {
id: string;
type: string;
};
fields: {
title: string;
description?: string;
file: {
url: string;
fileName: string;
contentType: string;
};
};
}>;
ministry?: Ministry;
author?: Author;
content: {
content: Array<{
content: Array<{
value: string;
marks?: Array<{ type: string }>;
}>;
nodeType: string;
}>;
nodeType: string;
};
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment