SOP 005: Create a Page
Fresh Last Updated: January 2025| Field | Value |
|---|---|
| SOP ID | SOP-005 |
| Version | 1.0 |
| Status | Active |
| Difficulty | Intermediate |
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
| Issue | Cause | Solution |
|---|---|---|
| 400 Invalid property | Property name mismatch | Use exact property names from schema |
| 400 Invalid option | Select option doesn't exist | Create option first or use existing |
| 404 Database not found | Wrong ID or no access | Verify ID and integration access |
| Missing content | Children not in array | Wrap blocks in children array |
Common Mistakes
- Wrong property name - Property names are case-sensitive and must match exactly
- Invalid select option - The option must exist in the database schema
- Missing title - Database pages require the title property to be set
- Nested blocks limit - You can only nest blocks 2 levels deep when creating