Claude
Skills
Sign in
โ† Back

notion-content-management

Included with Lifetime
$97 forever

Create, update, archive, and compose Notion pages and block content. Use when building pages programmatically, appending rich content blocks, updating page properties, or managing page lifecycle (archive/restore). Trigger with phrases like "notion create page", "notion add blocks", "notion update page", "notion archive page", "notion content", "notion block types", "notion rich text".

Productivitysaasproductivitynotion

What this skill does

# 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.

## Prerequisites

- Completed `notion-install-auth` setup
- `NOTION_TOKEN` environment variable set
- Target database or page shared with your integration (via Connections menu)
- `@notionhq/client` v2+ installed (TypeScript) or `notion-client` (Python)

## Instructions

### Step 1: Create, Update, and Archive Pages

Create a page in a database with typed properties and initial block content:

```typescript
import { Client } from '@notionhq/client';

const notion = new Client({ auth: process.env.NOTION_TOKEN });

// Create a page with properties and inline content
async function createPage(databaseId: string) {
  const page = await notion.pages.create({
    parent: { database_id: databaseId },
    icon: { emoji: '๐Ÿ“„' },
    cover: {
      external: { url: 'https://images.unsplash.com/photo-cover-id' },
    },
    properties: {
      // Title property (required for database pages)
      Name: {
        title: [{ text: { content: 'Q1 Sprint Retrospective' } }],
      },
      Status: {
        select: { name: 'In Progress' },
      },
      Priority: {
        select: { name: 'High' },
      },
      Tags: {
        multi_select: [{ name: 'Engineering' }, { name: 'Sprint' }],
      },
      'Due Date': {
        date: { start: '2026-04-01', end: '2026-04-05' },
      },
      Assignee: {
        people: [{ id: 'user-uuid-here' }],
      },
      Effort: {
        number: 8,
      },
      Done: {
        checkbox: false,
      },
      URL: {
        url: 'https://example.com/sprint-board',
      },
    },
    // Initial page body (block children)
    children: [
      {
        heading_2: {
          rich_text: [{ text: { content: 'Summary' } }],
        },
      },
      {
        paragraph: {
          rich_text: [{ text: { content: 'This page tracks the Q1 sprint retrospective.' } }],
        },
      },
    ],
  });

  console.log('Created page:', page.id);
  return page;
}
```

Update page properties after creation:

```typescript
async function updatePageProperties(pageId: string) {
  const updated = await notion.pages.update({
    page_id: pageId,
    properties: {
      Status: { select: { name: 'Done' } },
      Done: { checkbox: true },
      // Clear a property by setting to null
      'Due Date': { date: null },
    },
    // Update icon/cover
    icon: { emoji: 'โœ…' },
  });

  console.log('Updated page:', updated.id);
  return updated;
}
```

Archive and restore pages:

```typescript
// Archive (soft-delete)
async function archivePage(pageId: string) {
  await notion.pages.update({ page_id: pageId, archived: true });
  console.log('Archived page:', pageId);
}

// Restore from archive
async function restorePage(pageId: string) {
  await notion.pages.update({ page_id: pageId, archived: false });
  console.log('Restored page:', pageId);
}
```

### Step 2: Compose Content with Block Types

Append blocks to an existing page. Each block type has its own shape:

```typescript
async function appendBlocks(pageId: string) {
  await notion.blocks.children.append({
    block_id: pageId,
    children: [
      // Headings (heading_1, heading_2, heading_3)
      {
        heading_1: {
          rich_text: [{ text: { content: 'Project Overview' } }],
          is_toggleable: false,
        },
      },

      // Paragraph with rich text formatting
      {
        paragraph: {
          rich_text: [
            { text: { content: 'This is ' } },
            { text: { content: 'bold text' }, annotations: { bold: true } },
            { text: { content: ' and ' } },
            { text: { content: 'inline code' }, annotations: { code: true } },
            { text: { content: '. Visit ' } },
            {
              text: { content: 'our docs', link: { url: 'https://example.com' } },
              annotations: { italic: true },
            },
            { text: { content: '.' } },
          ],
        },
      },

      // Bulleted list items
      {
        bulleted_list_item: {
          rich_text: [{ text: { content: 'First bullet point' } }],
        },
      },
      {
        bulleted_list_item: {
          rich_text: [{ text: { content: 'Second bullet point' } }],
        },
      },

      // Numbered list items
      {
        numbered_list_item: {
          rich_text: [{ text: { content: 'Step one' } }],
        },
      },
      {
        numbered_list_item: {
          rich_text: [{ text: { content: 'Step two' } }],
        },
      },

      // To-do items
      {
        to_do: {
          rich_text: [{ text: { content: 'Review pull requests' } }],
          checked: false,
        },
      },
      {
        to_do: {
          rich_text: [{ text: { content: 'Update documentation' } }],
          checked: true,
        },
      },

      // Toggle block (collapsible)
      {
        toggle: {
          rich_text: [{ text: { content: 'Click to expand details' } }],
          children: [
            {
              paragraph: {
                rich_text: [{ text: { content: 'Hidden content inside toggle.' } }],
              },
            },
          ],
        },
      },

      // Code block
      {
        code: {
          rich_text: [{ text: { content: 'const x = 42;\nconsole.log(x);' } }],
          language: 'typescript',
          caption: [{ text: { content: 'Example snippet' } }],
        },
      },

      // Callout
      {
        callout: {
          rich_text: [{ text: { content: 'Important: review before merging.' } }],
          icon: { emoji: 'โš ๏ธ' },
          color: 'yellow_background',
        },
      },

      // Quote
      {
        quote: {
          rich_text: [{ text: { content: 'Ship early, ship often.' } }],
          color: 'gray',
        },
      },

      // Divider
      { divider: {} },

      // Image (external URL)
      {
        image: {
          external: { url: 'https://example.com/diagram.png' },
          caption: [{ text: { content: 'System architecture diagram' } }],
        },
      },

      // Table (3 columns x 2 rows)
      {
        table: {
          table_width: 3,
          has_column_header: true,
          has_row_header: false,
          children: [
            {
              table_row: {
                cells: [
                  [{ text: { content: 'Feature' } }],
                  [{ text: { content: 'Status' } }],
                  [{ text: { content: 'Owner' } }],
                ],
              },
            },
            {
              table_row: {
                cells: [
                  [{ text: { content: 'Auth' } }],
                  [{ text: { content: 'Done' } }],
                  [{ text: { content: 'Alice' } }],
                ],
              },
            },
          ],
        },
      },
    ],
  });

  console.log('Blocks appended to page:', pageId);
}
```

### Step 3: Update and Delete Individual Blocks

Retrieve, modify, and remove specific blocks:

```typescript
// List all child blocks of a page
async function listBlocks(pageId: string) {
  const blocks: any[] = [];
  let cursor: string | undefined;

  do {
    const response = await notion.blocks.children.list({
      block_id: pageId,
      start_cursor: cursor,
      page_size: 100,
    });
    blocks.push(...response.results);
    cursor = response.has_more ? response.next_cursor! : undefined;
  } while (cursor);

  return blocks;
}

// Update a specific block's content
async function updateBlock(blockId: string) {
  await notion.blocks.update({
    block_id: blockId,
    paragraph: {
      rich_text: [
        { text: { content: 'Updated paragraph content with ' } },
        { text: { content: 'new formatting' }, annotations: { bold: true, color: 'red' } },
      ],
    },
  });
  console.log('Block updated:', blockId);
}

// Upd

Related in Productivity