notion-content-management
'Create, update, archive, and compose Notion pages and block content.
Allowed Tools
Provided by Plugin
notion-pack
Claude Code skill pack for Notion (30 skills)
Installation
This skill is included in the notion-pack plugin:
/plugin install notion-pack@claude-code-plugins-plus
Click to copy
Instructions
Notion Content Management
Overview
Complete guide to creating, updating, archiving, and composing Notion pages and block content using the @notionhq/client SDK. Covers page lifecycle, all common block types, rich text formatting, and bulk content operations. The core workflow lives here at a high level; deep code walkthroughs are extracted into references/ so this file stays scannable.
Prerequisites
- Completed
notion-install-authsetup NOTION_TOKENenvironment variable set- Target database or page shared with the integration (via Connections menu)
@notionhq/clientv2+ installed (TypeScript) ornotion-client(Python)
Instructions
Step 1: Create, Update, and Archive Pages
Create a page in a database with typed properties (title, select, multi_select, date, people, number, checkbox, url), an optional icon/cover, and initial children block content. Update properties with pages.update (set a property to null to clear it). Archive is a soft-delete via archived: true, and restore flips it back to false.
Minimal skeleton:
import { Client } from '@notionhq/client';
const notion = new Client({ auth: process.env.NOTION_TOKEN });
const page = await notion.pages.create({
parent: { database_id: databaseId },
properties: { Name: { title: [{ text: { content: 'Q1 Retro' } }] } },
});
await notion.pages.update({ page_id: page.id, properties: { Status: { select: { name: 'Done' } } } });
await notion.pages.update({ page_id: page.id, archived: true }); // archive
Full typed-property create, update-with-clear, and archive/restore functions: page lifecycle walkthrough.
Step 2: Compose Content with Block Types
Append blocks to an existing page with blocks.children.append. Each block type has its own payload shape — headings, paragraphs (with rich text annotations), bulleted/numbered lists, to-dos, toggles, code blocks, callouts, quotes, dividers, images, and tables are all supported. The full catalog with the exact shape for every block type is in the block type catalog.
The minimal pattern:
await notion.blocks.children.append({
block_id: pageId,
children: [
{ heading_2: { rich_text: [{ text: { content: 'Notes' } }] } },
{
paragraph: {
rich_text: [
{ text: { content: 'Plain and ' } },
{ text: { content: 'bold' }, annotations: { bold: true } },
],
},
},
{ to_do: { rich_text: [{ text: { content: 'Review PRs' } }], checked: false } },
],
});
Step 3: Update and Delete Individual Blocks
Retrieve, modify, and remove specific blocks: blocks.children.list (paginate with start_cursor), blocks.update to change content or toggle a to-do's checked state, blocks.delete to trash a block (recoverable for 30 days), and blocks.retrieve to fetch one block.
Minimal skeleton:
await notion.blocks.update({ block_id: blockId, to_do: { checked: true } });
await notion.blocks.delete({ block_id: blockId });
Full paginated list, rich-text update, to-do toggle, delete, and retrieve helpers: block editing walkthrough.
Output
- Created pages with typed properties, icons, covers, and initial block content
- Updated page properties and metadata
- Archived and restored pages
- Appended all common block types: headings, paragraphs, lists, to-dos, toggles, code, callouts, quotes, dividers, images, and tables
- Retrieved, updated, and deleted individual blocks
Error Handling
| Error | Cause | Solution |
|---|---|---|
validation_error (400) |
Wrong property type or name | Retrieve database schema with databases.retrieve() to confirm property names and types |
objectnotfound (404) |
Page/block not shared with integration | Open the page in Notion, click ... > Connections > add the integration |
unauthorized (401) |
Invalid or expired token | Regenerate at notion.so/my-integrations and update NOTION_TOKEN |
rate_limited (429) |
Over 3 requests/second | Implement exponential backoff; read Retry-After header |
conflict_error (409) |
Concurrent edit to same block | Retry with fresh block data from blocks.retrieve() |
body too large (413) |
Over 100 blocks in one append | Batch into chunks of 100 blocks per blocks.children.append call |
Examples
A page builder composes a create call plus a structured blocks.children.append in sequence — for example, a standup note with heading2 sections, bulletedlistitem history, todo tasks, and a callout for blockers:
const page = await notion.pages.create({
parent: { database_id: databaseId },
properties: { Name: { title: [{ text: { content: `Standup ${new Date().toISOString().slice(0, 10)}` } }] } },
});
await notion.blocks.children.append({
block_id: page.id,
children: [
{ heading_2: { rich_text: [{ text: { content: 'Today' } }] } },
{ to_do: { rich_text: [{ text: { content: 'Build content module' } }], checked: false } },
],
});
Full worked examples — the complete page builder, a Python (notion-client) equivalent, and a chunked batch-append helper for payloads over 100 blocks — are in the worked examples reference.
Resources
- Working with Page Content
- Create a Page
- Update Page Properties
- Append Block Children
- Block Type Reference
- Rich Text Object
- @notionhq/client npm
- notion-sdk-py GitHub
Next, proceed to notion-data-handling for database queries, filtering, sorting, and pagination patterns.