Skip to main content

Content JSON Schema Reference

This document describes the required JSON schema for importing content into the Content Editor.

Field Specifications

Metadata Fields

FieldTypeRequiredDescription
titlestringYesThe main title of the content (max 255 chars recommended)
slugstringYesURL-friendly identifier (lowercase, hyphens, no spaces)
subtitlestringNoOptional subtitle or tagline
excerptstringNoBrief description for previews (150-200 chars recommended)
meta_titlestringNoSEO title (max 60 characters)
meta_descriptionstringNoSEO description (max 160 characters)

Classification Fields

FieldTypeRequiredAllowed Values
content_typestringNoblog, tutorial, lesson, tip, case_study
access_levelstringNopublic, registered, premium, course_specific
difficulty_levelstringNobeginner, intermediate, advanced
tagsarrayNoArray of strings (e.g., ["ai", "automation"])

Media Fields

FieldTypeRequiredDescription
featured_imagestringNoFull URL to image (must be valid URL format)
video_urlstringNoYouTube or Vimeo URL (must be valid URL format)

Content Field (TipTap JSON)

The content field uses TipTap/ProseMirror JSON format:

{
"content": {
"type": "doc",
"content": [ /* array of nodes */ ]
}
}

Quick Reference Schema

{
"title": "string (required)",
"slug": "string (required, URL-friendly)",
"subtitle": "string (optional)",
"excerpt": "string (optional)",
"content_type": "blog | tutorial | lesson | tip | case_study",
"access_level": "public | registered | premium | course_specific",
"difficulty_level": "beginner | intermediate | advanced",
"tags": ["array", "of", "strings"],
"featured_image": "string (optional, must be valid URL)",
"video_url": "string (optional, must be valid URL)",
"meta_title": "string (optional, max 60 chars)",
"meta_description": "string (optional, max 160 chars)",
"content": {
"type": "doc",
"content": [
{
"type": "heading | paragraph | bulletList | orderedList | blockquote | codeBlock | image | imageGallery | videoEmbed | youtube | mermaidDiagram | table",
"attrs": { }, // varies by node type (see detailed sections below)
"content": [...]
}
]
}
}

New Content Types Added:

  • imageGallery - Multiple images with captions and alt text
  • videoEmbed - Embed YouTube, Vimeo, or direct video files with captions
  • mermaidDiagram - Interactive diagrams (flowcharts, sequence diagrams, etc.)
  • Enhanced codeBlock - Now includes language selector and copy button

TipTap Node Types

Important: Use camelCase!

TipTap requires camelCase for all node type names:

  • bulletList (correct)
  • bullet_list (wrong)
  • orderedList (correct)
  • ordered_list (wrong)
  • listItem (correct)
  • list_item (wrong)
  • codeBlock (correct)
  • code_block (wrong)

Supported Node Types

  • Basic Content: heading, paragraph, bulletList, orderedList, listItem, blockquote
  • Code: codeBlock (enhanced with language selector and copy button)
  • Media: image, imageGallery, videoEmbed, youtube
  • Advanced: table, mermaidDiagram
  • Formatting: bold, italic, code, link, strike

1. Heading

{
"type": "heading",
"attrs": { "level": 2 },
"content": [
{ "type": "text", "text": "Your Heading Text" }
]
}
  • level: 1-6 (h1-h6)

2. Paragraph

{
"type": "paragraph",
"content": [
{ "type": "text", "text": "Your paragraph text here." }
]
}

3. Bullet List

{
"type": "bulletList",
"content": [
{
"type": "listItem",
"content": [
{
"type": "paragraph",
"content": [
{ "type": "text", "text": "List item 1" }
]
}
]
}
]
}

4. Ordered List

{
"type": "orderedList",
"content": [
{
"type": "listItem",
"content": [
{
"type": "paragraph",
"content": [
{ "type": "text", "text": "Step 1" }
]
}
]
}
]
}

5. Blockquote

{
"type": "blockquote",
"content": [
{
"type": "paragraph",
"content": [
{ "type": "text", "text": "This is a quote." }
]
}
]
}

6. Code Block (Enhanced)

{
"type": "codeBlock",
"attrs": { "language": "python" },
"content": [
{ "type": "text", "text": "print('Hello World')" }
]
}
  • Enhanced with language selector dropdown
  • Includes copy button functionality
  • Supported languages: javascript, typescript, python, java, csharp, cpp, c, go, rust, php, ruby, swift, kotlin, html, css, scss, json, yaml, xml, sql, bash, shell, powershell, markdown, plaintext
{
"type": "imageGallery",
"attrs": {
"images": [
{
"url": "https://example.com/image1.jpg",
"alt": "Image 1 description",
"caption": "Caption for image 1"
},
{
"url": "https://example.com/image2.jpg",
"alt": "Image 2 description",
"caption": "Caption for image 2"
}
]
}
}
  • Supports multiple images in a grid layout
  • Each image can have alt text and caption
  • Images are displayed in a responsive grid

8. Video Embed

{
"type": "videoEmbed",
"attrs": {
"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"caption": "Optional video caption",
"width": 640,
"height": 360
}
}
  • Supports YouTube URLs (watch or embed format)
  • Supports Vimeo URLs
  • Supports direct video files (.mp4, .webm, .ogg)
  • Optional caption and custom dimensions

9. Mermaid Diagram

{
"type": "mermaidDiagram",
"attrs": {
"code": "graph TD\n A[Start] --> B[Process]\n B --> C[End]"
}
}
  • Supports all Mermaid diagram types (flowchart, sequence, class, state, etc.)
  • Code is stored as a string with newlines
  • Renders interactive diagrams
  • Reference: Mermaid Documentation

Text Formatting (Marks)

Text nodes can have formatting marks:

Bold

{
"type": "text",
"marks": [{ "type": "bold" }],
"text": "Bold text"
}

Italic

{
"type": "text",
"marks": [{ "type": "italic" }],
"text": "Italic text"
}

Inline Code

{
"type": "text",
"marks": [{ "type": "code" }],
"text": "code()"
}
{
"type": "text",
"marks": [
{
"type": "link",
"attrs": {
"href": "https://example.com",
"target": "_blank"
}
}
],
"text": "Link text"
}

Combined Marks

{
"type": "text",
"marks": [
{ "type": "bold" },
{ "type": "italic" }
],
"text": "Bold and italic"
}

Complete Example

See content-template.json for a complete, working example with all node types.

Validation Rules

  1. JSON must be valid - No syntax errors
  2. Root must be object - Cannot be an array or primitive
  3. Content must have type "doc" - Top-level content type
  4. Content must have content array - Array of child nodes
  5. Enum values must match - content_type, access_level, difficulty_level
  6. URLs must be valid - If provided, featured_image and video_url must be proper URLs
  7. Tags must be array - If provided, tags must be an array of strings

Import Process

  1. Open Content Editor
  2. Click "Import JSON" button
  3. Click "Show Required Schema" to view this reference
  4. Paste your JSON
  5. Click "Import Content"
  6. Fix any validation errors if they appear
  7. Manually select Category and Course/Track (these are not imported)
  8. Save or Publish

Common Errors

❌ Using snake_case instead of camelCase

{ "type": "bullet_list" } // Wrong
{ "type": "bulletList" } // Correct

❌ Missing paragraph wrapper in list items

{
"type": "listItem",
"content": [
{ "type": "text", "text": "Item" } // Wrong - no paragraph
]
}
{
"type": "listItem",
"content": [
{
"type": "paragraph",
"content": [
{ "type": "text", "text": "Item" } // Correct
]
}
]
}

❌ Invalid enum value

{ "content_type": "article" } // Wrong - not in allowed values
{ "content_type": "blog" } // Correct

Need Help?

  • View the complete example: content-template.json
  • Check validation errors in the import modal
  • Refer to TipTap documentation: https://tiptap.dev/