# Notion Sync Best Practices & Troubleshooting Guide

**Last Updated:** 2026-03-15  
**Purpose:** Document best practices for syncing markdown content to Notion, preventing common issues, and optimizing for performance.

---

## 🎯 Overview

This guide covers the robust Notion sync process for International Expansion Strategy pages and provides best practices for all Notion sync operations.

**Key Improvements:**
- ✅ Proper toggle nesting (all content indented with tabs)
- ✅ Content validation before sync
- ✅ Error handling and retry logic
- ✅ Child page preservation
- ✅ Table formatting fixes
- ✅ Performance optimizations

---

## 🔧 Common Issues & Solutions

### Issue 1: Empty H2 Toggles

**Symptoms:**
- Toggle blocks appear empty in Notion
- Content flows outside the toggle as separate blocks

**Root Cause:**
Content after `{toggle="true"}` must be indented with tabs for Notion to nest it properly.

**Solution:**
Use `fix_h2_toggle_nesting()` function that indents ALL content inside toggles:
- Regular text and paragraphs
- H3, H4, H5, H6 headings
- Tables (all rows)
- Lists (bulleted, numbered, task lists)
- Code blocks
- Horizontal rules
- Callouts (`::: callout`)
- Child page references (`<page url=...>`)

**Example:**
```markdown
## 📊 Executive Summary {toggle="true"}

	**GSC Data:**
	- Total clicks: 79,728
	- Total impressions: 6,289,780

	### Key Insights
	
	| Market | Clicks | CTR |
	|---|--------|-----|
	| UK | 101 | 0.21% |
```

**Note:** All content inside the toggle is indented with a single tab (`\t`).

---

### Issue 2: Missing Content

**Symptoms:**
- Some sections don't appear in Notion
- Content seems truncated

**Root Cause:**
- Content not properly indented inside toggles
- Child pages added after toggle nesting fix
- Table formatting issues causing parsing errors

**Solution:**
1. **Order of Operations:**
   ```python
   content = remove_h1_title(content)
   content = validate_table_formatting(content)
   content = ensure_child_pages(content, page_id)  # Add BEFORE toggle fix
   content = fix_h2_toggle_nesting(content)        # Fix AFTER adding child pages
   ```

2. **Validate Before Sync:**
   - Run `--validate-only` flag to check for issues
   - Fix all validation errors before syncing
   - Verify content length matches expectations

---

### Issue 3: Table Formatting Errors

**Symptoms:**
- Tables don't render correctly in Notion
- Alignment colons (`:---:`) cause parsing issues

**Root Cause:**
Notion prefers simple table separators (`|---|`) without alignment colons.

**Solution:**
Use `validate_table_formatting()` function that:
- Replaces `|:---:|`, `|:---|`, `|---:|` with `|---|`
- Ensures consistent separator format
- Preserves table structure

**Before:**
```markdown
| Header | Header |
|:------:|:------:|
| Data   | Data   |
```

**After:**
```markdown
| Header | Header |
|---|-----|
| Data   | Data   |
```

---

### Issue 4: Child Page References Missing

**Symptoms:**
- Child pages not linked in parent page
- Page hierarchy broken

**Root Cause:**
Child page references (`<page url=...>`) must be:
1. Added before toggle nesting fix
2. Indented if inside a toggle
3. Placed at the end of content

**Solution:**
Use `ensure_child_pages()` function that:
- Checks if child pages already exist
- Adds them at the end of content
- Indents them if inside a toggle
- Preserves existing references

---

## 📋 Sync Process Workflow

### Step 1: Prepare Content

```bash
python3 v2/scripts/notion/sync-international-expansion-robust.py --validate-only
```

**What it does:**
- Removes H1 titles (Notion uses page titles separately)
- Fixes table formatting
- Adds child page references
- Fixes toggle nesting
- Validates content

**Output:**
- Prepared markdown files in `/tmp/notion-sync/international-expansion/`
- JSON sync files (`*-sync.json`) ready for MCP tool

---

### Step 2: Validate Content

**Validation Checks:**
- ✅ Toggle nesting (all content indented)
- ✅ Table formatting (no alignment colons)
- ✅ Content length (not too short)
- ✅ Child page references (if applicable)

**If validation fails:**
- Review validation errors
- Fix source markdown files
- Re-run preparation

---

### Step 3: Sync to Notion

**Using MCP Tool:**
```python
call_mcp_tool(
    server='project-0-landingpage-notion',
    toolName='notion-update-page',
    arguments={
        "page_id": "...",
        "command": "replace_content",
        "new_str": "..."
    }
)
```

**Or use automated sync:**
The robust sync script prepares JSON files that can be used with MCP tool directly.

---

## 🚀 Performance Optimizations

### Batch Processing

**Current Approach:**
- Prepare all pages first (fast, parallelizable)
- Validate all pages (catches issues early)
- Sync sequentially (prevents rate limiting)

**Optimization:**
- Use `--validate-only` flag for quick checks
- Prepare JSON files once, reuse for multiple syncs
- Cache prepared content to avoid re-processing

### Error Handling

**Retry Logic:**
- If sync fails, retry once after 2 seconds
- Log errors for debugging
- Continue with remaining pages

**Validation First:**
- Always validate before syncing
- Fix issues in source files, not prepared files
- Re-prepare after fixes

---

## 📝 Best Practices

### 1. Source File Formatting

**DO:**
- Use `{toggle="true"}` syntax for H2 toggles
- Keep tables simple (no alignment colons)
- Use consistent markdown formatting
- Add child page references in source (optional)

**DON'T:**
- Manually indent toggle content (script handles it)
- Use complex table formatting
- Mix markdown syntaxes
- Hardcode page IDs in content

---

### 2. Toggle Structure

**Correct:**
```markdown
## Section Title {toggle="true"}

Content here (will be auto-indented)
- List items
- More items

### Subsection

More content
```

**Incorrect:**
```markdown
## Section Title {toggle="true"}
Content here (not indented - will be empty in Notion)
```

---

### 3. Table Formatting

**Correct:**
```markdown
| Header | Header |
|---|-----|
| Data   | Data   |
```

**Incorrect:**
```markdown
| Header | Header |
|:------:|:------:|
| Data   | Data   |
```

---

### 4. Child Page References

**Correct:**
```markdown
## Appendix {toggle="true"}

Content here...

<page url="https://www.notion.so/page-id-1">
<page url="https://www.notion.so/page-id-2">
```

**Note:** Child pages are automatically indented if inside a toggle.

---

## 🔍 Troubleshooting

### Toggle Still Empty After Sync

**Check:**
1. Is content indented with tabs (not spaces)?
2. Are H3 headings indented?
3. Are tables indented?
4. Is content inside the toggle (not after next H2)?

**Fix:**
- Re-run preparation script
- Check prepared file in `/tmp/notion-sync/`
- Verify indentation with: `grep -n "^[^\t]" prepared-file.md`

---

### Content Missing After Sync

**Check:**
1. Is content length correct?
2. Are there validation errors?
3. Did sync complete successfully?
4. Are child pages preserved?

**Fix:**
- Check sync logs for errors
- Verify JSON file content matches source
- Re-sync if needed

---

### Table Rendering Issues

**Check:**
1. Are table separators simple (`|---|`)?
2. Are tables indented if inside toggle?
3. Are there any special characters?

**Fix:**
- Run table formatting validation
- Check prepared file table structure
- Simplify table formatting if needed

---

## 📊 Validation Checklist

Before syncing, verify:

- [ ] All H2 toggles have content indented with tabs
- [ ] H3 headings inside toggles are indented
- [ ] Tables use simple separators (`|---|`)
- [ ] Tables inside toggles are indented
- [ ] Child page references are included (if needed)
- [ ] Child page references are indented (if inside toggle)
- [ ] Content length matches expectations
- [ ] No validation errors reported

---

## 🛠️ Scripts Reference

### `sync-international-expansion-robust.py`

**Purpose:** Robust sync script with validation and error handling

**Usage:**
```bash
# Validate only
python3 v2/scripts/notion/sync-international-expansion-robust.py --validate-only

# Prepare for sync (dry run)
python3 v2/scripts/notion/sync-international-expansion-robust.py --dry-run

# Prepare for sync
python3 v2/scripts/notion/sync-international-expansion-robust.py
```

**Features:**
- Content validation
- Toggle nesting fix
- Child page preservation
- Error handling
- Progress tracking

---

### `prepare-international-expansion-sync.py`

**Purpose:** Simple preparation script (legacy, use robust version)

**Usage:**
```bash
python3 v2/scripts/notion/prepare-international-expansion-sync.py
```

**Note:** Use `sync-international-expansion-robust.py` for new syncs.

---

## 📚 Related Documentation

- `docs/development/MCP_INTEGRATION.md` - MCP tool usage
- `docs/ai/cursor-playbook.md` - AI workflow guide
- `v2/scripts/notion/README.md` - Notion sync scripts overview

---

## ✅ Quick Reference

**Sync Command:**
```bash
python3 v2/scripts/notion/sync-international-expansion-robust.py
```

**Validate Only:**
```bash
python3 v2/scripts/notion/sync-international-expansion-robust.py --validate-only
```

**Check Prepared Files:**
```bash
ls -lh /tmp/notion-sync/international-expansion/*.md
ls -lh /tmp/notion-sync/international-expansion/*-sync.json
```

**Verify Toggle Nesting:**
```bash
grep -A 5 '{toggle="true"}' /tmp/notion-sync/international-expansion/*.md | head -20
```

---

**Last Updated:** 2026-03-15  
**Maintained By:** Development Team  
**Review Frequency:** Quarterly or when issues arise
