> contentful
You are an expert in Contentful, the API-first content platform for enterprise teams. You help developers integrate Contentful's Content Delivery API (CDN-backed, read), Content Management API (write), and Content Preview API (draft content) into websites and apps — using typed content models, localization, rich text rendering, image transformations, and webhooks for build triggers.
curl "https://skillshub.wtf/TerminalSkills/skills/contentful?format=md"Contentful — Enterprise Headless CMS
You are an expert in Contentful, the API-first content platform for enterprise teams. You help developers integrate Contentful's Content Delivery API (CDN-backed, read), Content Management API (write), and Content Preview API (draft content) into websites and apps — using typed content models, localization, rich text rendering, image transformations, and webhooks for build triggers.
Core Capabilities
Content Delivery API
// src/lib/contentful.ts — Contentful client setup
import { createClient, type Entry, type Asset } from "contentful";
const client = createClient({
space: process.env.CONTENTFUL_SPACE_ID!,
accessToken: process.env.CONTENTFUL_DELIVERY_TOKEN!,
// For draft preview:
// accessToken: process.env.CONTENTFUL_PREVIEW_TOKEN,
// host: "preview.contentful.com",
});
// TypeScript interfaces matching content model
interface BlogPostFields {
title: string;
slug: string;
excerpt: string;
body: Document; // Rich Text
featuredImage: Asset;
author: Entry<AuthorFields>;
tags: string[];
publishDate: string;
}
// Fetch entries with type safety
async function getBlogPosts(limit = 10): Promise<Entry<BlogPostFields>[]> {
const response = await client.getEntries<BlogPostFields>({
content_type: "blogPost",
order: ["-fields.publishDate"],
limit,
include: 2, // Resolve 2 levels of linked entries
"fields.slug[exists]": true, // Only entries with slug
});
return response.items;
}
async function getBlogPostBySlug(slug: string) {
const response = await client.getEntries<BlogPostFields>({
content_type: "blogPost",
"fields.slug": slug,
include: 3,
limit: 1,
});
return response.items[0] || null;
}
Rich Text Rendering
// src/components/RichTextRenderer.tsx — Render Contentful rich text
import { documentToReactComponents, Options } from "@contentful/rich-text-react-renderer";
import { BLOCKS, INLINES, Document } from "@contentful/rich-text-types";
import Image from "next/image";
const renderOptions: Options = {
renderNode: {
[BLOCKS.EMBEDDED_ASSET]: (node) => {
const { title, file } = node.data.target.fields;
return (
<Image
src={`https:${file.url}`}
alt={title}
width={file.details.image.width}
height={file.details.image.height}
className="rounded-lg my-6"
/>
);
},
[BLOCKS.EMBEDDED_ENTRY]: (node) => {
const entry = node.data.target;
if (entry.sys.contentType.sys.id === "codeBlock") {
return (
<pre className="bg-gray-900 p-4 rounded-lg overflow-x-auto">
<code className={`language-${entry.fields.language}`}>
{entry.fields.code}
</code>
</pre>
);
}
return null;
},
[INLINES.HYPERLINK]: (node, children) => (
<a href={node.data.uri} className="text-blue-600 underline" target="_blank" rel="noopener">
{children}
</a>
),
},
};
export function RichText({ document }: { document: Document }) {
return <div className="prose max-w-none">{documentToReactComponents(document, renderOptions)}</div>;
}
Image Transformations
// Contentful Images API — resize, crop, format on the fly
function contentfulImageUrl(asset: Asset, options?: {
width?: number;
height?: number;
quality?: number;
format?: "webp" | "avif" | "jpg" | "png";
fit?: "pad" | "fill" | "scale" | "crop" | "thumb";
focus?: "face" | "center" | "top" | "bottom";
}) {
const url = new URL(`https:${asset.fields.file.url}`);
if (options?.width) url.searchParams.set("w", String(options.width));
if (options?.height) url.searchParams.set("h", String(options.height));
if (options?.quality) url.searchParams.set("q", String(options.quality));
if (options?.format) url.searchParams.set("fm", options.format);
if (options?.fit) url.searchParams.set("fit", options.fit);
if (options?.focus) url.searchParams.set("f", options.focus);
return url.toString();
}
// Usage: auto-optimize for web
<Image
src={contentfulImageUrl(post.fields.featuredImage, {
width: 800,
format: "webp",
quality: 80,
})}
alt={post.fields.title}
/>
Installation
npm install contentful # Delivery SDK
npm install @contentful/rich-text-react-renderer # Rich text → React
npm install contentful-management # Management API (write)
Best Practices
- Delivery API for reads — Use CDN-backed Delivery API for production; Preview API only for draft preview
- Type generation — Use
contentful-typescript-codegento generate TypeScript types from your content model - Rich text renderer — Always use
@contentful/rich-text-react-rendererwith custom renderers for embedded assets and entries - Image API — Transform images on the fly with URL params; serve WebP with quality 80 for 70% size reduction
- Webhooks for builds — Configure webhooks to trigger Vercel/Netlify builds on publish; ISR for immediate updates
- Localization — Set up locales in Contentful; fetch with
locale: "de"orlocale: "*"for all locales - Include depth — Set
include: 2-3to resolve linked entries; avoids N+1 queries for related content - Environment branching — Use Contentful Environments (like Git branches) for content model changes; merge to master when ready
> related_skills --same-repo
> zustand
You are an expert in Zustand, the small, fast, and scalable state management library for React. You help developers manage global state without boilerplate using Zustand's hook-based stores, selectors for performance, middleware (persist, devtools, immer), computed values, and async actions — replacing Redux complexity with a simple, un-opinionated API in under 1KB.
> zoho
Integrate and automate Zoho products. Use when a user asks to work with Zoho CRM, Zoho Books, Zoho Desk, Zoho Projects, Zoho Mail, or Zoho Creator, build custom integrations via Zoho APIs, automate workflows with Deluge scripting, sync data between Zoho apps and external systems, manage leads and deals, automate invoicing, build custom Zoho Creator apps, set up webhooks, or manage Zoho organization settings. Covers Zoho CRM, Books, Desk, Projects, Creator, and cross-product integrations.
> zod
You are an expert in Zod, the TypeScript-first schema declaration and validation library. You help developers define schemas that validate data at runtime AND infer TypeScript types at compile time — eliminating the need to write types and validators separately. Used for API input validation, form validation, environment variables, config files, and any data boundary.
> zipkin
Deploy and configure Zipkin for distributed tracing and request flow visualization. Use when a user needs to set up trace collection, instrument Java/Spring or other services with Zipkin, analyze service dependencies, or configure storage backends for trace data.