Skip to content
contentful logo

Contentful CMS

contentful

Manages content with Contentful headless CMS and Content Delivery API. Use when building content-driven applications with structured content models, CDN delivery, and enterprise content management.

SKILL.md

Full skill instructions

Contentful CMS

Enterprise headless CMS with Content Delivery API, global CDN, and powerful content modeling. Separate content from presentation for any frontend.

Quick Start

npm install contentful
import { createClient } from 'contentful';

const client = createClient({
  space: 'your_space_id',
  accessToken: 'your_access_token',  // Delivery API token
});

// Fetch entries
const entries = await client.getEntries();
console.log(entries.items);

API Types

APIPurposeToken Type
Content DeliveryPublished contentDelivery token
Content PreviewDraft contentPreview token
Content ManagementCreate/​update contentManagement token
// Preview API client
const previewClient = createClient({
  space: 'your_space_id',
  accessToken: 'preview_access_token',
  host: 'preview.contentful.com'
});

Fetching Entries

Get All Entries

const entries = await client.getEntries();

entries.items.forEach((entry) => {
  console.log(entry.fields);
});

Filter by Content Type

const posts = await client.getEntries({
  content_type: 'blogPost'
});

Get Single Entry

const entry = await client.getEntry('entry_id');
console.log(entry.fields.title);

Query Parameters

const posts = await client.getEntries({
  content_type: 'blogPost',

  // Field equality
  'fields.slug': 'hello-world',

  // Comparison operators
  'fields.publishDate[lte]': new Date().toISOString(),
  'fields.rating[gt]': 4,

  // Text search
  'fields.title[match]': 'javascript',

  // Existence
  'fields.featuredImage[exists]': true,

  // Array contains
  'fields.tags[in]': 'react,typescript',

  // Ordering
  order: '-fields.publishDate',  // desc
  order: 'fields.title',          // asc

  // Pagination
  skip: 0,
  limit: 10,

  // Locale
  locale: 'en-US',

  // Include linked entries (depth 1-10)
  include: 2,

  // Select specific fields
  select: 'fields.title,fields.slug,fields.author'
});

Search Operators

// [ne] - Not equal
'fields.status[ne]': 'draft'

// [in] - In array
'fields.category[in]': 'tech,design,business'

// [nin] - Not in array
'fields.category[nin]': 'archive'

// [exists] - Field exists
'fields.image[exists]': true

// [lt], [lte], [gt], [gte] - Comparisons
'fields.price[gte]': 100,
'fields.price[lte]': 500

// [match] - Full-text search
'fields.body[match]': 'react hooks'

// [near] - Location proximity
'fields.location[near]': '40.7128,-74.0060'

// [within] - Location within bounding box
'fields.location[within]': '40.7,-74.1,40.8,-74.0'

Linked Entries (References)

// Include linked entries (default: 1)
const posts = await client.getEntries({
  content_type: 'blogPost',
  include: 3  // Follow 3 levels of references
});

// Access linked author
posts.items.forEach((post) => {
  // Linked entries are resolved automatically
  const author = post.fields.author;
  console.log(author.fields.name);
});

Assets (Images & Files)

// Get all assets
const assets = await client.getAssets();

// Get single asset
const asset = await client.getAsset('asset_id');

console.log(asset.fields.title);
console.log(asset.fields.file.url);  // URL (add https:)

// Image transformations via URL
const imageUrl = `https:${asset.fields.file.url}?w=800&h=600&fit=fill`;

Image API Parameters

const url = `https:${image.fields.file.url}`;

// Resize
`${url}?w=800&h=600`

// Fit modes
`${url}?fit=pad`      // Add padding
`${url}?fit=fill`     // Resize to fit
`${url}?fit=scale`    // Scale proportionally
`${url}?fit=crop`     // Crop to size
`${url}?fit=thumb`    // Thumbnail

// Focus area (for crop)
`${url}?f=face`       // Focus on face
`${url}?f=faces`      // Focus on faces
`${url}?f=center`     // Center focus

// Format
`${url}?fm=webp`      // WebP
`${url}?fm=jpg`       // JPEG
`${url}?fm=png`       // PNG

// Quality (1-100)
`${url}?q=80`

// Combined
`${url}?w=400&h=300&fit=fill&fm=webp&q=80`

Sync API

Keep local content in sync with delta updates.

// Initial sync
const response = await client.sync({
  initial: true
});

// Store these
const { entries, assets, nextSyncToken } = response;

// Later: Get only changes
const deltaResponse = await client.sync({
  nextSyncToken: storedNextSyncToken
});

// Contains only changed/​deleted items
const { entries, deletedEntries, assets, deletedAssets } = deltaResponse;

Rich Text Rendering

npm install @contentful/​rich-text-react-renderer @contentful/​rich-text-types
import { documentToReactComponents } from '@contentful/​rich-text-react-renderer';
import { BLOCKS, INLINES } from '@contentful/​rich-text-types';

const options = {
  renderNode: {
    [BLOCKS.EMBEDDED_ASSET]: (node) => {
      const { file, title } = node.data.target.fields;
      return <img src={`https:${file.url}`} alt={title} />;
    },
    [BLOCKS.EMBEDDED_ENTRY]: (node) => {
      const entry = node.data.target;
      // Render embedded entry
      return <Card data={entry.fields} />;
    },
    [INLINES.HYPERLINK]: (node, children) => {
      return <a href={node.data.uri} target="_blank">{children}</​a>;
    }
  }
};

function RichText({ content }) {
  return <div>{documentToReactComponents(content, options)}</​div>;
}

TypeScript

Generate Types

npm install -D cf-content-types-generator
npx cf-content-types-generator --out src/​types/​contentful.d.ts

Type-Safe Queries

import { createClient, Entry, EntryCollection } from 'contentful';
import { IBlogPost, IBlogPostFields } from './​types/​contentful';

const client = createClient({
  space: process.env.CONTENTFUL_SPACE_ID!,
  accessToken: process.env.CONTENTFUL_ACCESS_TOKEN!
});

// Typed response
const posts: EntryCollection<IBlogPostFields> = await client.getEntries({
  content_type: 'blogPost'
});

posts.items.forEach((post: Entry<IBlogPostFields>) => {
  console.log(post.fields.title);  // TypeScript knows this exists
});

Next.js Integration

// lib/​contentful.ts
import { createClient } from 'contentful';

export const client = createClient({
  space: process.env.CONTENTFUL_SPACE_ID!,
  accessToken: process.env.CONTENTFUL_ACCESS_TOKEN!
});

export const previewClient = createClient({
  space: process.env.CONTENTFUL_SPACE_ID!,
  accessToken: process.env.CONTENTFUL_PREVIEW_TOKEN!,
  host: 'preview.contentful.com'
});

export function getClient(preview = false) {
  return preview ? previewClient : client;
}
// app/​posts/[slug]/​page.tsx
import { client } from '@/​lib/​contentful';
import { documentToReactComponents } from '@contentful/​rich-text-react-renderer';

export async function generateStaticParams() {
  const entries = await client.getEntries({
    content_type: 'blogPost',
    select: 'fields.slug'
  });

  return entries.items.map((entry) => ({
    slug: entry.fields.slug
  }));
}

export default async function PostPage({ params }: { params: { slug: string } }) {
  const entries = await client.getEntries({
    content_type: 'blogPost',
    'fields.slug': params.slug,
    include: 2
  });

  const post = entries.items[0];

  return (
    <article>
      <h1>{post.fields.title}</​h1>
      <p>By {post.fields.author.fields.name}</​p>
      {documentToReactComponents(post.fields.body)}
    </​article>
  );
}

Preview Mode (Next.js)

// app/​api/​preview/​route.ts
import { draftMode } from 'next/​headers';
import { redirect } from 'next/​navigation';

export async function GET(request: Request) {
  const { searchParams } = new URL(request.url);
  const secret = searchParams.get('secret');
  const slug = searchParams.get('slug');

  if (secret !== process.env.CONTENTFUL_PREVIEW_SECRET) {
    return new Response('Invalid token', { status: 401 });
  }

  draftMode().enable();
  redirect(`/​posts/​${slug}`);
}

// In page: use preview client when draftMode is enabled
import { draftMode } from 'next/​headers';
import { getClient } from '@/​lib/​contentful';

export default async function Page({ params }) {
  const { isEnabled } = draftMode();
  const client = getClient(isEnabled);
  // ...
}

Content Management API

For creating/​updating content programmatically.

npm install contentful-management
import { createClient } from 'contentful-management';

const client = createClient({
  accessToken: 'management_token'
});

// Get space and environment
const space = await client.getSpace('space_id');
const environment = await space.getEnvironment('master');

// Create entry
const entry = await environment.createEntry('blogPost', {
  fields: {
    title: { 'en-US': 'New Post' },
    slug: { 'en-US': 'new-post' },
    body: { 'en-US': { /​* rich text */ } }
  }
});

// Publish
await entry.publish();

// Update entry
entry.fields.title['en-US'] = 'Updated Title';
await entry.update();

// Upload asset
const asset = await environment.createAssetFromFiles({
  fields: {
    title: { 'en-US': 'My Image' },
    file: {
      'en-US': {
        contentType: 'image/​jpeg',
        fileName: 'image.jpg',
        file: fs.createReadStream('image.jpg')
      }
    }
  }
});

await asset.processForAllLocales();
await asset.publish();

Webhooks

Configure in Contentful dashboard to trigger on:

  • Entry publish/​unpublish
  • Asset upload/​delete
  • Content type changes
// app/​api/​contentful-webhook/​route.ts
export async function POST(request: Request) {
  const body = await request.json();

  // Verify webhook (optional but recommended)
  const signature = request.headers.get('x-contentful-signature');

  // Handle based on event type
  const { sys } = body;

  if (sys.type === 'Entry') {
    // Revalidate specific page
    await fetch(`/​api/​revalidate?path=/​posts/​${body.fields.slug['en-US']}`);
  }

  return new Response('OK');
}

Best Practices

  1. Use preview API for draft/​unpublished content
  2. Set appropriate include depth (default 1, max 10)
  3. Select only needed fields for performance
  4. Use sync API for large datasets
  5. Cache responses - content doesn't change frequently
  6. Use webhooks for on-demand revalidation

More skills from majiayu000

xiaohongshu logo
majiayu000/claude-arsenal

xiaohongshu

xiaohongshu

286 148
View
agent-task-conductor logo
majiayu000/claude-skill-registry

agent-task-conductor

Conduct multi-agent task orchestration and workflow coordination.

663 1
View
conductor-setup logo
majiayu000/claude-skill-registry

conductor-setup

Initialize project with Conductor artifacts (product definition,

663 1
View
animation-designer logo
majiayu000/claude-skill-registry

animation-designer

Expert in web animations, transitions, and motion design using Framer Motion and CSS

663 1
View
diagramming logo
majiayu000/claude-skill-registry

diagramming

Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...

663 1
View
h3-pg logo
majiayu000/claude-skill-registry-data

h3-pg

PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.

23 1
View
conductor-development logo
majiayu000/claude-skill-registry

conductor-development

Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...

663 1
View
conductor-status logo
majiayu000/claude-skill-registry

conductor-status

Display project status, active tracks, and next actions

663 1
View
dockerization logo
majiayu000/claude-skill-registry

dockerization

Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.

663 1
View

Popular AI tools

Kaiber logo
Video

Kaiber

Generate, edit, and beat-sync AI video with leading models in one workspace.

Paid
View
Vimcal logo
Productivity

Vimcal

The world's fastest calendar for remote work

Free
View

Transform Your Design with AI Designer by ImgCreator.ai

Freemium
View
Akool AI logo
Content & writing

Akool AI

Revolutionizing Video Production with AI-Powered Creativity

Paid
View

Extend an image past the frame and let AI fill the new aspect ratio.

Freemium
View
StarByFace logo
Security

StarByFace

Discover your celebrity doppelgänger with StarByFace!

Free
View
C

ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.

Freemium
View
Opus Clip logo
Coding & apps

Opus Clip

Opus.ai: Revolutionize Your Web Experience

Free
View