Back to Blog

How to implement Visual Editing with Contentful

April 21, 2025
3 min read
Development

Integrating a Custom Rich Text Editor with Contentful

A comprehensive guide to implementing the custom-built rich text editor that works with Contentful in your own projects.

1. Dependencies Installation

# Install core dependencies
pnpm add @tiptap/core @tiptap/react @tiptap/starter-kit
pnpm add @tiptap/extension-heading @tiptap/extension-link @tiptap/extension-image
pnpm add @tiptap/extension-placeholder @tiptap/extension-color @tiptap/extension-text-style

# Install Contentful SDKs
pnpm add contentful contentful-management

These packages provide the foundation for the rich text editing functionality and Contentful integration.

2. Copy Component Files

Copy these key files from the current project to your new project:

  • components/ui/rich-text-editor.tsx - The main editor component
  • lib/contentful.ts - Contentful client configuration
  • lib/contentful-management.ts - For content management operations

3. Set Up Environment Variables

Add to your .env.local file:

# Contentful API keys
CONTENTFUL_SPACE_ID=your_space_id
CONTENTFUL_ACCESS_TOKEN=your_delivery_api_key
CONTENTFUL_MANAGEMENT_TOKEN=your_management_token
CONTENTFUL_ENVIRONMENT=master

4. Set Up Content Model in Contentful

  1. Create a Rich Text content type in Contentful with these fields:
    • title (Short text)
    • content (Rich Text)
    • Any other fields you need (category, author, etc.)

5. Implement Basic Usage

// Example component using the editor
import { RichTextEditor } from "@/components/ui/rich-text-editor";
import { useState } from "react";

export default function BlogEditor() {
  const [content, setContent] = useState("<p>Initial content...</p>");
  
  const handleContentSave = async (newContent: string) => {
    // Save to Contentful using the management API
    // Example code:
    try {
      // Entry update logic here
      return Promise.resolve();
    } catch (error) {
      console.error("Failed to save content:", error);
      return Promise.reject(error);
    }
  };

  return (
    <div className="max-w-4xl mx-auto">
      <h1 className="text-2xl font-bold mb-4">Blog Editor</h1>
      <RichTextEditor
        initialContent={content}
        isAuthorizedEditor={true}
        onSave={handleContentSave}
        placeholder="Write your content here..."
      />
    </div>
  );
}

6. Fetch and Display Content

// Example of fetching and displaying content
import { getBlogPost } from "@/lib/contentful";

export default async function BlogPost({ slug }) {
  const post = await getBlogPost(slug);
  
  return (
    <div className="max-w-4xl mx-auto">
      <h1 className="text-3xl font-bold">{post.fields.title}</h1>
      <div 
        className="prose max-w-none mt-6"
        dangerouslySetInnerHTML={{ __html: post.fields.content }}
      />
    </div>
  );
}

7. Implement Save Functionality

In your editing components:

import { updateBlogPostContent } from "@/lib/contentful-management";

// Inside component:
const handleSave = async (newContent) => {
  try {
    await updateBlogPostContent(postId, newContent);
    return Promise.resolve();
  } catch (error) {
    return Promise.reject(error);
  }
};

8. Add Authorization Check

Ensure only authorized users can edit content:

import { useAuth } from "@/lib/auth-context";

// Inside component:
const { isAuthenticated, isAuthorizedEditor } = useAuth();

// Then pass to editor
<RichTextEditor
  isAuthorizedEditor={isAuthorizedEditor}
  // ...other props
/>

9. Style Integration

  1. Make sure you have the necessary CSS for your editor:
    • If using Tailwind: copy relevant classes from your current project
    • If using CSS modules: copy the editor stylesheet
  2. Add any custom button styles needed for your editor toolbar

Key Features of Your Custom Editor

  • Authentication Integration: Built-in permission checking
  • Contentful-ready: Formatted for Contentful's Rich Text field
  • Inline Editing: Edit content directly in the page layout
  • Full Toolbar: Formatting, links, images, etc.
  • Responsive Design: Works on different screen sizes

The integration leverages the TipTap editor and provides a seamless interface between your frontend and Contentful's content management APIs.