Skip to content

SOP 005: Create a Page

Fresh Last Updated: January 2025
FieldValue
SOP IDSOP-005
Version1.0
StatusActive
DifficultyIntermediate

Purpose

Create pages in Notion databases or as children of other pages, including setting properties and adding content blocks.

Prerequisites

  • [ ] Completed authentication setup (SOP 002)
  • [ ] Target database ID or parent page ID
  • [ ] Insert content capability enabled
  • [ ] Integration has access to parent

Page Creation Flow

Step-by-Step Instructions

Step 1: Create Page in Database

javascript
const { Client } = require('@notionhq/client');
require('dotenv').config();

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

async function createDatabasePage() {
  const response = await notion.pages.create({
    parent: {
      database_id: process.env.NOTION_DATABASE_ID
    },
    properties: {
      // Title property (required)
      Name: {
        title: [
          {
            text: {
              content: 'My New Task'
            }
          }
        ]
      },
      // Select property
      Status: {
        select: {
          name: 'In Progress'
        }
      },
      // Number property
      Priority: {
        number: 2
      },
      // Date property
      'Due Date': {
        date: {
          start: '2025-02-15',
          end: '2025-02-20'  // Optional end date
        }
      },
      // Multi-select property
      Tags: {
        multi_select: [
          { name: 'Backend' },
          { name: 'Urgent' }
        ]
      },
      // Checkbox property
      Archived: {
        checkbox: false
      }
    }
  });

  console.log('✅ Page created:', response.id);
  return response;
}

Step 2: Create Page as Child of Another Page

javascript
async function createChildPage(parentPageId) {
  const response = await notion.pages.create({
    parent: {
      page_id: parentPageId
    },
    properties: {
      title: {
        title: [
          {
            text: {
              content: 'Child Page Title'
            }
          }
        ]
      }
    }
  });

  return response;
}

Step 3: Property Types Reference

javascript
Name: {
  title: [
    {
      text: { content: 'Page Title' }
    }
  ]
}
javascript
Description: {
  rich_text: [
    {
      text: { content: 'Plain text' }
    },
    {
      text: {
        content: 'Bold text',
        link: { url: 'https://example.com' }
      },
      annotations: { bold: true }
    }
  ]
}
javascript
Priority: {
  number: 42
}

Price: {
  number: 99.99
}
javascript
Status: {
  select: { name: 'Done' }
}

// Clear selection
Status: {
  select: null
}
javascript
Tags: {
  multi_select: [
    { name: 'Tag1' },
    { name: 'Tag2' }
  ]
}
javascript
// Single date
'Due Date': {
  date: { start: '2025-01-15' }
}

// Date range
'Event Period': {
  date: {
    start: '2025-01-15',
    end: '2025-01-20'
  }
}

// With time
'Meeting': {
  date: {
    start: '2025-01-15T09:00:00.000-05:00',
    time_zone: 'America/New_York'
  }
}
javascript
Completed: {
  checkbox: true
}
javascript
Website: {
  url: 'https://example.com'
}
javascript
Contact: {
  email: 'user@example.com'
}
javascript
Assignee: {
  people: [
    { id: 'user-id-1' },
    { id: 'user-id-2' }
  ]
}
javascript
'Related Tasks': {
  relation: [
    { id: 'page-id-1' },
    { id: 'page-id-2' }
  ]
}

Step 4: Create Page with Content Blocks

javascript
async function createPageWithContent(databaseId) {
  const response = await notion.pages.create({
    parent: { database_id: databaseId },
    properties: {
      Name: {
        title: [{ text: { content: 'Project Documentation' } }]
      }
    },
    children: [
      // Heading 1
      {
        object: 'block',
        type: 'heading_1',
        heading_1: {
          rich_text: [{ text: { content: 'Introduction' } }]
        }
      },
      // Paragraph
      {
        object: 'block',
        type: 'paragraph',
        paragraph: {
          rich_text: [
            { text: { content: 'This document outlines the project ' } },
            {
              text: { content: 'requirements' },
              annotations: { bold: true }
            },
            { text: { content: ' and implementation details.' } }
          ]
        }
      },
      // Bulleted list
      {
        object: 'block',
        type: 'bulleted_list_item',
        bulleted_list_item: {
          rich_text: [{ text: { content: 'First item' } }]
        }
      },
      {
        object: 'block',
        type: 'bulleted_list_item',
        bulleted_list_item: {
          rich_text: [{ text: { content: 'Second item' } }]
        }
      },
      // Code block
      {
        object: 'block',
        type: 'code',
        code: {
          rich_text: [{ text: { content: 'console.log("Hello!");' } }],
          language: 'javascript'
        }
      },
      // Callout
      {
        object: 'block',
        type: 'callout',
        callout: {
          rich_text: [{ text: { content: 'Important note here' } }],
          icon: { emoji: '💡' }
        }
      },
      // To-do list
      {
        object: 'block',
        type: 'to_do',
        to_do: {
          rich_text: [{ text: { content: 'Task to complete' } }],
          checked: false
        }
      },
      // Divider
      {
        object: 'block',
        type: 'divider',
        divider: {}
      }
    ]
  });

  return response;
}

Step 5: Create Page with Icon and Cover

javascript
async function createPageWithMedia(databaseId) {
  const response = await notion.pages.create({
    parent: { database_id: databaseId },
    icon: {
      type: 'emoji',
      emoji: '🚀'
    },
    cover: {
      type: 'external',
      external: {
        url: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d'
      }
    },
    properties: {
      Name: {
        title: [{ text: { content: 'Launch Plan' } }]
      }
    }
  });

  return response;
}

// Using external icon URL
async function createPageWithExternalIcon(databaseId) {
  const response = await notion.pages.create({
    parent: { database_id: databaseId },
    icon: {
      type: 'external',
      external: {
        url: 'https://example.com/icon.png'
      }
    },
    properties: {
      Name: {
        title: [{ text: { content: 'Custom Icon Page' } }]
      }
    }
  });

  return response;
}

Step 6: Bulk Create Pages

javascript
async function bulkCreatePages(databaseId, items) {
  const results = [];

  for (const item of items) {
    try {
      const page = await notion.pages.create({
        parent: { database_id: databaseId },
        properties: {
          Name: {
            title: [{ text: { content: item.name } }]
          },
          Status: {
            select: { name: item.status || 'To Do' }
          },
          Priority: {
            number: item.priority || 3
          }
        }
      });

      results.push({ success: true, id: page.id, name: item.name });

      // Respect rate limits
      await new Promise(resolve => setTimeout(resolve, 350));

    } catch (error) {
      results.push({ success: false, name: item.name, error: error.message });
    }
  }

  return results;
}

// Usage
const items = [
  { name: 'Task 1', status: 'In Progress', priority: 1 },
  { name: 'Task 2', status: 'To Do', priority: 2 },
  { name: 'Task 3', priority: 3 }
];

const results = await bulkCreatePages(databaseId, items);
console.table(results);

Complete Example

javascript
async function createCompleteTask() {
  const databaseId = process.env.NOTION_DATABASE_ID;

  const response = await notion.pages.create({
    parent: { database_id: databaseId },
    icon: { emoji: '📋' },
    properties: {
      Name: {
        title: [{ text: { content: 'Implement User Authentication' } }]
      },
      Status: {
        select: { name: 'In Progress' }
      },
      Priority: {
        number: 1
      },
      'Due Date': {
        date: {
          start: '2025-01-20',
          end: '2025-01-25'
        }
      },
      Tags: {
        multi_select: [
          { name: 'Backend' },
          { name: 'Security' }
        ]
      }
    },
    children: [
      {
        heading_2: {
          rich_text: [{ text: { content: 'Acceptance Criteria' } }]
        }
      },
      {
        to_do: {
          rich_text: [{ text: { content: 'User can sign up with email' } }],
          checked: true
        }
      },
      {
        to_do: {
          rich_text: [{ text: { content: 'User can log in with credentials' } }],
          checked: false
        }
      },
      {
        to_do: {
          rich_text: [{ text: { content: 'Password reset functionality' } }],
          checked: false
        }
      },
      {
        heading_2: {
          rich_text: [{ text: { content: 'Technical Notes' } }]
        }
      },
      {
        paragraph: {
          rich_text: [{ text: { content: 'Use JWT for session management. Store refresh tokens in httpOnly cookies.' } }]
        }
      }
    ]
  });

  console.log('✅ Task created:', response.url);
  return response;
}

Verification Checklist

  • [ ] Page appears in database/parent
  • [ ] All properties set correctly
  • [ ] Content blocks render properly
  • [ ] Icon and cover display (if set)
  • [ ] Page URL accessible

Troubleshooting

IssueCauseSolution
400 Invalid propertyProperty name mismatchUse exact property names from schema
400 Invalid optionSelect option doesn't existCreate option first or use existing
404 Database not foundWrong ID or no accessVerify ID and integration access
Missing contentChildren not in arrayWrap blocks in children array

Common Mistakes

  1. Wrong property name - Property names are case-sensitive and must match exactly
  2. Invalid select option - The option must exist in the database schema
  3. Missing title - Database pages require the title property to be set
  4. Nested blocks limit - You can only nest blocks 2 levels deep when creating

See Also

Built with VitePress | Powered by Claude AI