Search documentation

Find pages, sections, and snippets across the Clog docs.

Block types

Every block that can appear in a post or page body — JSON shape, constraints, rendering notes.

A post or page bodyJson is an array of typed blocks. Each block is an object with a discriminator field type plus type-specific fields. v1 ships 13 block types, listed below in alphabetical order.

The same vocabulary is used for the derived structuredBlocks array a post carries when its schemaType has a non-trivial structuredData payload — the recipe card, how-to steps, etc. project into the same blocks, so the consumer renders them with the same renderer it uses for the body.

Per-body cap: 1,000 blocks per post or page.

Stored vs. response shape

The Image block has two shapes:

WhereShape
When you POST / PATCH a body{ type: 'image', mediaId, alt?, caption? } — no url.
When you read a body{ type: 'image', mediaId, alt?, caption?, url: string | null } — Clog joins the referenced media row and inlines the resolved public URL.

Every other block variant is identical in both shapes.

url can be null if the underlying media row was deleted after the block was saved — render a fallback rather than emitting a broken <img>. See Posts → Image blocks and edits for why this happens.

Inline Markdown

The text-bearing fields on prose blocks (paragraph.text, heading.text, quote.text, quote.attribution, list.items[], callout.body, callout.title) carry raw Markdown source. Only inline marks are in scope — **bold**, _italic_, `code`, [link](url). Block-level Markdown (headings, lists, code blocks) is each its own block type, so you only need an inline parser. See API → Rendering content for the rendering recipe.

The 13 block types

callout

A highlighted note. One of four variants.

{
  "type": "callout",
  "variant": "info",
  "title": "Optional title (inline Markdown)",
  "body": "Body text (inline Markdown)."
}
FieldTypeNotes
variant'info' | 'warning' | 'success' | 'error'Required. Drives icon and tint on the rendered output.
titlestring?Optional bold lead line. Inline Markdown.
bodystringRequired. Inline Markdown.

code

A code block with a language hint.

{
  "type": "code",
  "language": "ts",
  "code": "console.log('hello');"
}
FieldTypeNotes
languagestringA shortname / extension (ts, tsx, bash, json, python, ...). The consumer passes it to its syntax highlighter.
codestringRaw code. Render in a <pre><code> block.

cta

A call-to-action card with a title, body, and a single link.

{
  "type": "cta",
  "title": "Read the full guide",
  "body": "A short pitch for what's on the other side of the link.",
  "linkUrl": "https://example.com/guide",
  "linkLabel": "Read the guide →",
  "variant": "default"
}
FieldTypeNotes
titlestringRequired. The card's main heading.
bodystringRequired. Short description. Inline Markdown is fine.
linkUrlstringRequired. Absolute or relative URL.
linkLabelstringRequired. The button / link label.
variant'default' | 'outlined'Required. Two visual treatments.

divider

A visual section break (a horizontal rule on most sites).

{ "type": "divider" }

No fields beyond type.


faq

An accordion of question / answer pairs. When present in a post body, drives FAQPage JSON-LD on the consumer side.

{
  "type": "faq",
  "items": [
    { "question": "What is X?", "answer": "X is …" },
    { "question": "How do I Y?", "answer": "You Y by …" }
  ]
}
FieldTypeNotes
items{ question, answer }[]1–50 items. Both fields required per item.

heading

A subheading. H2, H3, or H4 only (the page title is the H1).

{
  "type": "heading",
  "level": 2,
  "text": "On naming things",
  "id": "on-naming-things"
}
FieldTypeNotes
level2 | 3 | 4Required.
textstringRequired. Inline Markdown supported.
idstring?Optional anchor id. Auto-derived from text (kebab-case) when omitted. Duplicate slugs across heading blocks in the same body are disambiguated with a numeric suffix.

Heading blocks feed the post's derived tocItems — see Rendering content → derived helpers.


image

An image from the workspace's media library.

{
  "type": "image",
  "mediaId": "0a4b3c2d-1234-4567-89ab-cdef01234567",
  "alt": "A photo of …",
  "caption": "Caption shown below the image.",
  "url": "https://storage.example.com/.../image.png"
}
FieldTypeNotes
mediaIdstring (UUID)Required. Must reference a media row in the same workspace; cross-workspace references are rejected.
altstring?Optional. Falls back to the media row's alt field when not set per-block.
captionstring?Optional. Falls back to the media row's caption.
urlstring | nullResponse-only. Resolved public URL — see Stored vs. response shape above.

Editor-side: cropping or resizing an image in the post editor creates a new media row and repoints the block; the original is untouched. See Posts → Image blocks and edits.


key_takeaways

A short bullet list, typically shown at the top of a post as a TL;DR.

{
  "type": "key_takeaways",
  "items": [
    "First takeaway.",
    "Second takeaway.",
    "Third."
  ]
}
FieldTypeNotes
itemsstring[]1–10 items. Each is plain text (no inline Markdown).

list

An unordered or ordered list.

{
  "type": "list",
  "style": "bullet",
  "items": [
    "First item.",
    "Second item with **bold**.",
    "Third item."
  ]
}
FieldTypeNotes
style'bullet' | 'ordered'Required.
itemsstring[]Required. Each item supports inline Markdown.

paragraph

Default prose. The most common block in any post.

{
  "type": "paragraph",
  "text": "A paragraph of prose with **inline marks** and [links](https://example.com)."
}
FieldTypeNotes
textstringRequired. Up to 10,000 characters. Inline Markdown supported.

quote

A block quote with an optional attribution line.

{
  "type": "quote",
  "text": "The quote itself, with **inline marks** if you want them.",
  "attribution": "Author Name, Source"
}
FieldTypeNotes
textstringRequired. Inline Markdown supported.
attributionstring?Optional. Rendered below the quote (typically as a <cite>).

tweet_embed

A Tweet / X embed. The consumer typically stamps the X embed script and renders a <blockquote class="twitter-tweet">.

{
  "type": "tweet_embed",
  "url": "https://twitter.com/anthropicai/status/1234567890"
}
FieldTypeNotes
urlstringRequired. The full tweet URL.

video_embed

A YouTube, Vimeo, or generic video URL. The consumer renders an <iframe> or wraps a player of choice. When present in a post body with schemaType = VideoObject, drives VideoObject JSON-LD.

{
  "type": "video_embed",
  "url": "https://www.youtube.com/embed/dQw4w9WgXcQ",
  "title": "Optional title shown over the player"
}
FieldTypeNotes
urlstringRequired. Embed URL (YouTube's /embed/<id>, Vimeo's /video/<id>, etc.).
titlestring?Optional. Useful for accessibility / iframe title.

Derived helpers (on the post response)

Three fields the backend derives from bodyJson on every save and ships on the read response. None of them are blocks — they're flat fields you read directly:

FieldShapeUse for
bodyTextstringPlain-text projection of the body (whitespace-joined block text). Excerpts, search indexing, character counts.
tocItems{ level: 2|3|4, text, id }[]A sidebar table of contents. Walks heading blocks in document order.
readingTimeMinnumberceil(wordCount / 230), minimum 1. Pages don't carry this — only posts.

On this page