Skip to content

Packt Content Format

Content within the Content Lake is stored in Packt Content Format (PCF), a JSON-based rich text specification designed for modern publishing. PCF provides a structured, serialisable representation of content that can be rendered into any output format -- HTML, Markdown, SSML, ePub, PDF, and beyond.

PCF is heavily influenced by Portable Text by Sanity.io. Any valid Portable Text document is a valid PCF document.

PCF has two complementary layers:

  1. The Content Layer -- A JSON structure representing the document content (this page).
  2. The Entity Overlay -- A separate JSON document that annotates the content with knowledge graph references (see Entities).

Output Format Comparison

The same content expressed in each supported output format:

{
    "style": "h1",
    "_type": "block",
    "_key": "f4a901bc12e7",
    "children": [
        {
            "_type": "span",
            "_key": "a1b2c3d4e5f6",
            "text": "Introduction"
        }
    ]
},
{
    "_type": "block",
    "_key": "9a85015a4de8",
    "style": "normal",
    "markDefs": [
        {
            "_type": "link",
            "_key": "c233e5cbac18",
            "href": "https://www.packtpub.com"
        }
    ],
    "children": [
        {
            "_type": "span",
            "_key": "37c3818c5d6b",
            "text": "Introducing the ",
            "marks": []
        },
        {
            "_type": "span",
            "_key": "b086edb3fed9",
            "marks": [
                "c233e5cbac18"
            ],
            "text": "Packt"
        },
        {
            "_type": "span",
            "_key": "aa3ef773326d",
            "marks": [],
            "text": " content format to enhance publishing flows and integrate context to content."
        }
    ]
}
# Introduction

Introducing the [Packt](https://www.packtpub.com) content format
to enhance publishing flows and integrate context to content.
<h1>Introduction</h1>

<p>Introducing the <a href="https://www.packtpub.com">Packt</a>
content format to enhance publishing flows and integrate context
to content.</p>
Chapter One, Introduction. Introducing the Packt content format
to enhance publishing flows and integrate context to content.

Document Structure

A PCF document is a JSON array of blocks:

[
    { "_type": "block", "_key": "abc123" },
    { "_type": "image", "_key": "def456" },
    { "_type": "block", "_key": "ghi789" }
]

Every element in the root array must have:

Field Type Required Description
_type string Yes The block type identifier
_key string Yes A document-unique key for this block

Text Blocks

A text block represents a paragraph, heading, list item, or blockquote.

{
    "_type": "block",
    "_key": "9a85015a4de8",
    "style": "normal",
    "markDefs": [],
    "children": []
}
Field Type Required Default Description
_type string Yes "block" Always "block" for text blocks
_key string Yes -- Document-unique identifier
style string Yes "normal" "normal", "h1" -- "h6", "blockquote"
markDefs array No [] Annotation definitions for child spans
children array Yes -- Array of spans and inline objects
listItem string No null List type: "bullet", "number", "square", "letter"
level integer No null Nesting depth for list items (1-based)

Spans

A span is the inline text unit within a block.

{
    "_type": "span",
    "_key": "37c3818c5d6b",
    "text": "Hello, world.",
    "marks": []
}
Field Type Required Description
_type string Yes Always "span"
_key string Yes Block-unique identifier
text string Yes The text content
marks array Yes Decorator names or markDef keys

Marks

Marks annotate spans with formatting or data. There are two kinds: decorators (simple string values) and annotations (references to structured definitions in markDefs).

Decorators

Simple string values in the marks array:

Decorator Meaning
"strong" Bold
"em" Italic
"underline" Underline
"strike" Strikethrough
"code" Inline code
"superscript" Superscript
"subscript" Subscript

Annotations

Annotations reference entries in the block's markDefs array and carry structured data. A span references an annotation by including the annotation's _key in its marks array.

{
    "_type": "block",
    "_key": "9a85015a4de8",
    "style": "normal",
    "markDefs": [
        {
            "_type": "link",
            "_key": "c233e5cbac18",
            "href": "https://www.packtpub.com",
            "title": "Packt Publishing"
        }
    ],
    "children": [
        {
            "_type": "span",
            "_key": "37c3818c5d6b",
            "text": "Visit ",
            "marks": []
        },
        {
            "_type": "span",
            "_key": "b086edb3fed9",
            "marks": ["c233e5cbac18"],
            "text": "Packt Publishing"
        },
        {
            "_type": "span",
            "_key": "aa3ef773326d",
            "marks": [],
            "text": " for more."
        }
    ]
}

In this example, the span containing "Packt Publishing" includes "c233e5cbac18" in its marks array. That key matches the link definition in markDefs, so the span is rendered as a hyperlink.

Standard Annotation Types

Type Purpose Rendered?
link External hyperlink Yes
internalLink Cross-document content link (contentlake:// URI) Yes
footnote Page-level note with rich text body Yes
endnote Document-level note with rich text body Yes
citation Structured bibliographic reference Yes
crossRef Intra-document block reference Yes
comment Editorial workflow annotation No
{
    "_type": "link",
    "_key": "lnk1",
    "href": "https://www.packtpub.com",
    "title": "Packt Publishing"
}

Internal links use the contentlake:// URI scheme to reference other documents within the Content Lake:

contentlake://{tenant}/{documentId}/{blockKey}
{
    "_type": "internalLink",
    "_key": "il1",
    "href": "contentlake://packt/doc-abc123/blk-789"
}

Footnotes and Endnotes

Footnotes and endnotes carry a rich text body as a nested PCF block array. Serialisers auto-number footnotes sequentially within the page or document.

{
    "_type": "footnote",
    "_key": "fn1",
    "body": [
        {
            "_type": "block",
            "_key": "fnb1",
            "style": "normal",
            "children": [
                {
                    "_type": "span",
                    "_key": "fns1",
                    "text": "See the original paper for details.",
                    "marks": []
                }
            ]
        }
    ]
}

Citations

Citations carry structured bibliographic data:

{
    "_type": "citation",
    "_key": "cit1",
    "citationKey": "knuth1997",
    "authors": ["Donald E. Knuth"],
    "title": "The Art of Computer Programming",
    "year": 1997,
    "publisher": "Addison-Wesley",
    "isbn": "978-0201896831"
}

Supported fields: authors, title, year, publisher, venue, doi, url, isbn, pages, citationKey.

Lists

Lists are consecutive blocks with a listItem property. There is no wrapper element -- list structure is derived from sequence and level values.

[
    {
        "_type": "block",
        "_key": "li1",
        "style": "normal",
        "listItem": "bullet",
        "level": 1,
        "children": [
            {
                "_type": "span",
                "_key": "lis1",
                "text": "First item",
                "marks": []
            }
        ]
    },
    {
        "_type": "block",
        "_key": "li2",
        "style": "normal",
        "listItem": "bullet",
        "level": 2,
        "children": [
            {
                "_type": "span",
                "_key": "lis2",
                "text": "Nested item",
                "marks": []
            }
        ]
    },
    {
        "_type": "block",
        "_key": "li3",
        "style": "normal",
        "listItem": "bullet",
        "level": 1,
        "children": [
            {
                "_type": "span",
                "_key": "lis3",
                "text": "Second item",
                "marks": []
            }
        ]
    }
]

Serialisers group consecutive blocks sharing the same listItem type into list containers. A change in level opens or closes nested lists accordingly.

Custom Block Types

Type Description
image Static images with captions, alt text, and asset refs
video Embedded video with provider metadata
codeBlock Syntax-highlighted code listings
aside Callouts, tips, warnings with a semantic tone value
formula Mathematical expressions (LaTeX/KaTeX)
table Structured tabular data with rich-text cells

Custom types beyond these are permitted. A serialiser that encounters an unrecognised _type should skip the block gracefully -- it must not fail.

Images

Image blocks store the image source, accessibility text, display properties, and responsive size variants. The children array provides a rich text description that can be used for extended alt text or audio descriptions.

{
    "_key": "79973aed956a",
    "_type": "image",
    "src": "/images/portable-text-logo.png",
    "alt": "Portable Text Editor logo",
    "props": {
        "type": "png",
        "height": 800,
        "width": 800,
        "resolution": "2x",
        "dpi": 1200
    },
    "sizes": [
        { "original": "/images/portable-text-logo.png" },
        { "1.5x": "/images/portable-text-logo.png 1.5x" },
        { "2x": "/images/portable-text-logo.png 2x" },
        { "4x": "/images/portable-text-logo.png 4x" }
    ],
    "children": [
        {
            "_type": "span",
            "_key": "37c3818c5d6b",
            "text": "This is a detailed alt text by ",
            "marks": []
        },
        {
            "_type": "span",
            "_key": "b086edb3fed9",
            "marks": ["strong"],
            "text": "the Content Lake"
        },
        {
            "_type": "span",
            "_key": "aa3ef773326d",
            "marks": [],
            "text": " which can contain lists and other formatting to enhance use-cases like audio descriptions."
        }
    ]
}
Field Type Required Description
_type string Yes Always "image"
_key string Yes Document-unique identifier
src string Yes Path or URL to the default image asset
alt string Yes Short accessibility text
props object No Image metadata (type, dimensions, DPI)
sizes array No Responsive variants keyed by resolution
children array No Rich text description for extended alt text

Serialisation

PCF is designed to be serialised to any target format:

  1. For "block" types, render children spans applying marks and styles.
  2. For custom types, render the type-specific structure.
  3. For unknown types, skip gracefully or render a placeholder.

Serialisers should walk the root array in order, maintaining state for list grouping (consecutive listItem blocks) and footnote numbering. Each block is self-contained apart from those two concerns, so parallel or partial rendering is straightforward.

Compatibility with Portable Text

PCF is a superset of Portable Text. The block, span, markDefs, and marks system works identically. PCF extends Portable Text in three ways:

  1. _key is required on all blocks and spans (Portable Text treats it as optional).
  2. Additional standard types such as aside, formula, and table are defined.
  3. The Entity Overlay system annotates content with knowledge graph references without modifying the content layer (see Entities).

Any Portable Text serialiser can render PCF content. Custom block types and annotations will be skipped by serialisers that do not recognise them, which is the expected behaviour.