Awesome-omni-skill notion-management

Complete guide for working with Notion API in Node.js/JavaScript projects. Use when creating, updating, fetching, or managing Notion pages, databases, and properties. Includes proper handling of rich text, database schemas, multi-select fields, dates, and complex content structures. Triggers on tasks like "create a Notion page," "update database properties," "add content to Notion," or "manage Notion workflows."

install
source · Clone the upstream repo
git clone https://github.com/diegosouzapw/awesome-omni-skill
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/diegosouzapw/awesome-omni-skill "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/development/notion-management-jordinodejs" ~/.claude/skills/diegosouzapw-awesome-omni-skill-notion-management-f61602 && rm -rf "$T"
manifest: skills/development/notion-management-jordinodejs/SKILL.md
source content

Notion Management Skill

Master working with the Notion API for Node.js/JavaScript development. This skill provides patterns, tools, and references for all common Notion operations.

Quick Start

Fetching Notion Resources

// Fetch a page or database
const page = await notion_notion-fetch({
  id: "page-id-or-url"
});

// Pages return markdown content and properties
// Databases return schema, data sources, and views

Creating Pages

// Single page creation
const pages = await notion_notion-create-pages({
  pages: [{
    properties: {
      title: "My Page Title",
      // Other properties based on database schema
    },
    content: "# Markdown content here\n\nSupports rich markdown."
  }],
  parent: {
    data_source_id: "collection-id" // or page_id, or database_id
  }
});

Updating Pages

// Update properties
await notion_notion-update-page({
  page_id: "page-id",
  command: "update_properties",
  properties: {
    title: "Updated Title",
    status: "Done"
  }
});

// Replace all content
await notion_notion-update-page({
  page_id: "page-id",
  command: "replace_content",
  new_str: "# New content here"
});

// Replace specific section
await notion_notion-update-page({
  page_id: "page-id",
  command: "replace_content_range",
  selection_with_ellipsis: "# Old heading...last paragraph.",
  new_str: "# New heading\nNew content"
});

// Insert content after a section
await notion_notion-update-page({
  page_id: "page-id",
  command: "insert_content_after",
  selection_with_ellipsis: "## Section...end of section.",
  new_str: "\n## New Section\nNew content here"
});

Common Property Types and Formats

Simple Properties

  • title (string): Page title, shown as large heading
  • rich_text (string): Text field
  • url (string): URL field
  • email (string): Email field
  • phone_number (string): Phone number
  • checkbox (string): Use
    "__YES__"
    or
    "__NO__"
  • number (number): Use JavaScript numbers, not strings

Select Properties

// single_select: Just use the option name
properties: {
  Status: "In Progress"  // Must match exact option name
}

// multi_select: Single string or comma-separated
// ❌ WRONG: ["option1", "option2"]  // Don't use arrays
// ❌ WRONG: "option1,option2"       // Don't use commas
// ✅ CORRECT: Need to use separate API calls or specific format

Date Properties

// Date properties use expanded format with three keys
properties: {
  "date:Due Date:start": "2025-01-30",
  "date:Due Date:end": null,  // Optional end date
  "date:Due Date:is_datetime": 0  // 0 for date, 1 for datetime
}

Place Properties

// Place/location properties use expanded format
properties: {
  "place:Office:name": "HQ",
  "place:Office:address": "123 Main St",
  "place:Office:latitude": 37.7749,
  "place:Office:longitude": -122.4194,
  "place:Office:google_place_id": "optional-id"
}

Special Property Names

Properties named "id" or "url" (case-insensitive) must be prefixed with "userDefined:":

properties: {
  "userDefined:id": "value",
  "userDefined:URL": "https://example.com"
}

Multi-Select Fields - CRITICAL

Common mistake: Multi-select fields have strict validation. When creating or updating pages in a database with multi_select properties:

  1. Fetch the database first to see available options:

    const db = await notion_notion-fetch({ id: "database-id" });
    // Response shows: "Tags": {"options": [{"name": "Option1"}, {"name": "Option2"}]}
    
  2. Use only valid option names:

    properties: {
      Tags: "Option1"  // Single option as string
    }
    
  3. For multiple options: Currently the API has limitations. Best practice:

    • Create the page with one tag
    • Update it with additional tags if needed
    • Or pass multiple tags separated by specific format (check database schema)
  4. Error handling: If you get "Invalid multi_select value", check:

    • Is the option name spelled exactly as shown in database?
    • Are you passing a string, not an array?
    • Does the database schema allow this option?

Database Operations

Fetch Database Schema

const db = await notion_notion-fetch({
  id: "database-id-or-url"
});

// Returns:
// - Database title and icon
// - Data sources (collections) within the database
// - Schema for each data source
// - Views available

Creating Databases

const db = await notion_notion-create-database({
  title: [{type: "text", text: {content: "My Database"}}],
  parent: {page_id: "parent-page-id"},
  properties: {
    "Task Name": {type: "title"},
    "Status": {
      type: "select",
      select: {
        options: [
          {name: "To Do", color: "red"},
          {name: "In Progress", color: "yellow"},
          {name: "Done", color: "green"}
        ]
      }
    },
    "Due Date": {type: "date"}
  }
});

Updating Database Schema

await notion_notion-update-database({
  database_id: "db-id",
  title: [{type: "text", text: {content: "New Title"}}],
  properties: {
    "New Property": {type: "rich_text"},
    "Property to Rename": {name: "Renamed Property"},
    "Property to Delete": null  // Set to null to remove
  }
});

Content (Markdown) Guidelines

Supported Markdown

  • Headings:
    # H1
    ,
    ## H2
    , etc.
  • Lists: Unordered
    - item
    , ordered
    1. item
  • Code: Inline
    `code`
    and code blocks
  • Bold/Italic:
    **bold**
    ,
    *italic*
  • Links:
    [text](url)
  • Tables: Full markdown table support
  • Quotes:
    > quoted text
  • Toggles/Collapsible:
    ▶ Collapsed content\n\tHidden items
    (Note: indentation with tabs)

Toggle/Collapsible Sections

Toggles are created with the

character followed by content that should be hidden:

▶ Click to expand
	Hidden content line 1
	Hidden content line 2
	- Nested list item

Important: Content after

must be indented with tabs or spaces.

Rich Text Annotations

Content can include color and style annotations:

# Heading {color="blue"}
Some text {color="red"} and {bold="true"}

Search and Navigation

Search Notion

const results = await notion_notion-search({
  query: "search term",
  query_type: "internal"  // or "user" for user search
});

// Filter by creation date
const filtered = await notion_notion-search({
  query: "recent docs",
  filters: {
    created_date_range: {
      start_date: "2025-01-01",
      end_date: "2025-01-31"
    }
  }
});

Fetch Teams and Users

// List teams
const teams = await notion_notion-get-teams({
  query: "engineering"  // optional search
});

// List users
const users = await notion_notion-get-users({
  query: "john",  // optional search
  page_size: 100
});

// Get specific user
const user = await notion_notion-get-users({
  user_id: "user-id-or-self"
});

Error Handling

Common Errors and Solutions

"Invalid multi_select value"

Cause: Option name doesn't exist or format is wrong Solution:

  1. Fetch database to see valid options
  2. Use exact option names
  3. Pass as string, not array

"Invalid input" / Validation error

Cause: Wrong property format or type Solution:

  1. Check property type in database schema
  2. Use correct format (e.g., date properties need date:Property:start format)
  3. Verify special names use userDefined: prefix

"Page not found"

Cause: Wrong ID or insufficient permissions Solution:

  1. Verify page/database ID is correct
  2. Check you have access to the resource
  3. Use full URL if ID doesn't work

"Unauthorized"

Cause: Notion integration doesn't have permission Solution:

  1. Verify integration is shared with the database/page
  2. Check integration scopes in Notion settings
  3. Re-authenticate if needed

Best Practices

  1. Always fetch first: Before creating content in a database, fetch the database to understand its schema
  2. Validate option names: Multi-select options are strictly validated—check exact spellings
  3. Use data_source_id for databases: When a database has multiple data sources, use
    data_source_id
    instead of
    database_id
    as parent
  4. Handle IDs flexibly: Most tools accept page IDs with or without dashes
  5. Content indentation: Toggle/collapsible content must use tabs or spaces for indentation
  6. Break up complex updates: Large content updates are safer when split into smaller operations
  7. Test with simple cases first: Before complex automation, test with a single page/field
  8. Document environment: Store Notion integration tokens securely, never in git

Advanced Patterns

See references/advanced-patterns.md for:

  • Batch operations and performance optimization
  • Syncing external data to Notion
  • Creating dynamic databases and views
  • Handling relationships and rollups
  • Complex filtering and sorting