Skip to content

Dynamic content

Overview

This guide explains how to render dynamic content. The content follows a structured JSON format that can be processed in any programming language. The system uses a document-based approach with nested elements and text formatting.

Document Structure

Dynamic content starts with a root document object:

json
{
	"type": "doc",
	"content": [
		// Array of content elements (paragraphs, headings, lists, etc.)
	]
}

Element Types and Their Structures

Paragraph

A basic text container for flowing content.

JSON Structure:

json
{
	"type": "paragraph",
	"content": [
		// Contains text elements and other inline content
	]
}

Heading

Hierarchical headings with levels 1-3.

JSON Structure:

json
{
	"type": "heading",
	"attrs": {
		"level": 2 // Number from 1 to 3
	},
	"content": [
		// Contains text elements
	]
}

Bullet List

Unordered list with list items.

JSON Structure:

json
{
	"type": "bulletList",
	"content": [
		// Contains listItem elements
	]
}

List Item

Individual items within a list.

JSON Structure:

json
{
	"type": "listItem",
	"content": [
		// Contains paragraph elements
	]
}

Text

The basic text content unit with optional formatting.

JSON Structure:

json
{
	"type": "text",
	"text": "Your text content here",
	"marks": [
		// Optional array of formatting marks
	]
}

Text Formatting (Marks System)

Text elements can include formatting marks that modify their appearance:

Available Mark Types

Bold

Makes text bold.

json
{ "type": "bold" }

Italic

Makes text italic.

json
{ "type": "italic" }

Creates a hyperlink.

json
{
	"type": "link",
	"attrs": {
		"href": "https://example.com",
		"target": "_blank" // Optional: "_blank" or "_self"
	}
}

Text Style

Applies color to text.

json
{
	"type": "textStyle",
	"attrs": {
		"color": "#3b82f6" // Hex color code
	}
}

Question Style

Special styling for question text (no attributes).

json
{ "type": "questionStyle" }

Rendering Logic

Processing Flow

  1. Start with the root document - Check if type is "doc"
  2. Iterate through content array - Process each element in order
  3. Handle element types - Use appropriate rendering for each element type
  4. Process nested content - Elements can contain other elements
  5. Apply text formatting - Handle marks on text elements

Element Processing Rules

For Document Root

  • If type is not "doc", the content is invalid
  • Process each item in the content array in sequence

For Paragraph Elements

  • Create a paragraph container (HTML: <p> tag)
  • Process all child elements within the paragraph
  • Join the results together

For Heading Elements

  • Use the attrs.level value to determine heading level (1-3)
  • Create appropriate heading element (HTML: <h1>, <h2>, <h3>)
  • Process text content within the heading
  • Headings typically don't need additional bold formatting

For List Elements

  • Create an unordered list container (HTML: <ul> tag)
  • For each listItem in content, create list items (HTML: <li> tags)
  • Process paragraph content within each list item

For Text inside dynamic content

  • If no marks are present, output plain text
  • If marks are present, apply formatting in this order:
    1. Apply bold/italic formatting
    2. Apply color styling
    3. Apply question styling
    4. Wrap in link if present

Mark Application Order

When multiple marks are present on text, apply them in this sequence:

  1. Basic formatting: bold and/or italic
  2. Color styling: text color from textStyle mark
  3. Special styling: question style class
  4. Link wrapping: hyperlink (applies to all inner formatting)

Complete Rendering Example

Input JSON

json
{
	"type": "doc",
	"content": [
		{
			"type": "heading",
			"attrs": { "level": 1 },
			"content": [
				{
					"type": "text",
					"text": "Welcome to Our Service",
					"marks": null
				}
			]
		},
		{
			"type": "paragraph",
			"content": [
				{
					"type": "text",
					"text": "This is a ",
					"marks": null
				},
				{
					"type": "text",
					"text": "sample paragraph",
					"marks": [
						{ "type": "bold" },
						{ "type": "textStyle", "attrs": { "color": "#3b82f6" } }
					]
				},
				{
					"type": "text",
					"text": " with ",
					"marks": null
				},
				{
					"type": "text",
					"text": "multiple formats",
					"marks": [
						{ "type": "italic" },
						{
							"type": "link",
							"attrs": { "href": "https://example.com" }
						}
					]
				}
			]
		},
		{
			"type": "bulletList",
			"content": [
				{
					"type": "listItem",
					"content": [
						{
							"type": "paragraph",
							"content": [
								{
									"type": "text",
									"text": "First list item",
									"marks": null
								}
							]
						}
					]
				},
				{
					"type": "listItem",
					"content": [
						{
							"type": "paragraph",
							"content": [
								{
									"type": "text",
									"text": "Second list item with ",
									"marks": null
								},
								{
									"type": "text",
									"text": "emphasis",
									"marks": [{ "type": "bold" }]
								}
							]
						}
					]
				}
			]
		}
	]
}

Rendered Output

html
<h1>Welcome to Our Service</h1>
<p>
	This is a
	<span style="color: #3b82f6"><strong>sample paragraph</strong></span> with
	<a href="https://example.com"><em>multiple formats</em></a>
</p>
<ul>
	<li><p>First list item</p></li>
	<li>
		<p>Second list item with <strong>emphasis</strong></p>
	</li>
</ul>

Displayed output UI

Displayed output UI

Implementation Guidelines

General Approach

  1. Create element handlers for each content type
  2. Use recursive processing for nested content
  3. Maintain proper HTML semantics or equivalent in your output format
  4. Escape text content to prevent injection issues
  5. Preserve content order as specified in the JSON

Styling Recommendations

  • Use semantic HTML tags where possible
  • Apply consistent spacing between elements
  • Consider accessibility when applying colors and styles
  • Maintain readable font sizes and contrast ratios