Proven - Implemented and validated with real API integration testing
Publishing markdown content to Notion workspaces is a core functionality for Piper Morgan’s knowledge management capabilities. This pattern addresses:
The Notion Publishing pattern implements a three-layer architecture:
cli/commands/publish.py)services/publishing/publisher.py)services/publishing/converters/)Core capabilities:
cli/commands/
publish.py # CLI interface with argparse
services/publishing/
publisher.py # Main orchestration service
converters/
markdown_to_notion.py # Markdown → Notion blocks conversion
services/integrations/
notion/
notion_integration_router.py # Notion API integration
tests/publishing/
test_publish_command.py # TDD suite with real API calls
CLI Usage:
# Publish to Notion page
python cli/commands/publish.py publish README.md --to notion --location parent-id
# Publish to Notion database (for ADRs)
python cli/commands/publish.py publish docs/adrs/adr-026.md --to notion --database db-id
Service Layer:
from services.publishing.publisher import Publisher
publisher = Publisher()
# Publish markdown file
result = await publisher.publish(
file_path="docs/guide.md",
platform="notion",
location=parent_page_id,
format="markdown"
)
if result["success"]:
print(f"Published: {result['url']}")
if result.get("warnings"):
print(f"Warnings: {result['warnings']}")
else:
print(f"Failed: {result['error']}")
Markdown Conversion:
from services.publishing.converters.markdown_to_notion import (
convert_markdown_to_notion_blocks
)
markdown_content = """
# My Document
This is a paragraph with **bold** text.
- List item 1
- List item 2
"""
result = convert_markdown_to_notion_blocks(markdown_content)
# Returns: {
# "success": True,
# "blocks": [...notion block objects...],
# "warnings": ["Unsupported element: ..." if any]
# }
Environment variables:
NOTION_API_KEY=secret_... # Notion integration token
User configuration (config/PIPER.user.md):
## Notion Configuration
- **parent_id.test**: [test-parent-page-id]
- **parent_id.docs**: [docs-parent-page-id]
- **database_id.adrs**: [adr-database-id]
Environment Loading:
# CRITICAL: Load environment variables FIRST in CLI commands
from dotenv import load_dotenv
load_dotenv()
# Then import services that depend on environment
from services.publishing.publisher import Publisher
Error Handling:
try:
result = await publisher.publish(...)
if result["success"]:
# Success path with warnings
if result.get("warnings"):
for warning in result["warnings"]:
print(f"⚠️ {warning}")
else:
# Failure path with actionable error
print(f"❌ {result['error']}")
except ValueError as e:
# User errors (invalid parent, bad configuration)
print(f"Configuration error: {e}")
except Exception as e:
# Unexpected errors
print(f"Unexpected error: {e}")
Test-Driven Development:
# Tests MUST use real API calls, not mocks for core functionality
@pytest.mark.integration
@pytest.mark.asyncio
async def test_publish_creates_actual_notion_page(test_parent_id, test_prefix):
"""CRITICAL: Verify publishing ACTUALLY creates page in Notion"""
publisher = Publisher()
result = await publisher.publish(
file_path=test_file,
platform="notion",
location=test_parent_id
)
# Verify in Notion (real API call)
notion = NotionMCPAdapter()
await notion.connect()
page = await notion.get_page(result["page_id"])
assert page is not None, "Created page not found in Notion"
Supported Markdown Elements (MVP scope):
cli/commands/publish.py:29-157 - CLI interface and command routingservices/publishing/publisher.py:14-293 - Main publisher service with dual-mode supportservices/publishing/converters/markdown_to_notion.py - Markdown conversion logictests/publishing/test_publish_command.py:32-68 - Integration test with real Notion APItests/publishing/test_publish_command.py:70-84 - Header conversion validationtests/publishing/test_publish_command.py:86-98 - Paragraph conversion validationtests/publishing/test_publish_command.py:100-112 - List conversion validationtests/publishing/test_publish_command.py:114-125 - Warning generation for unsupported elementsImplemented features:
Key learning preserved:
docs/internal/development/handoffs/prompts/2025-08-29-handoff-publish-complete.mdPattern created: October 8, 2025 Status: Proven - Implemented and validated with real API testing Maintenance: Active - Core knowledge management functionality