When to use
Use Notion sync when you need to:- Share SDD artifacts with stakeholders who prefer Notion
- Enable collaborative requirements editing in Notion
- Create a relational database view of the traceability chain
- Pull changes made in Notion back to local markdown files
- Maintain a single source of truth across SDD and Notion
Prerequisites
You must set two environment variables:| Variable | Purpose | How to get |
|---|---|---|
NOTION_API_KEY | Notion integration API key | Create a Notion integration at notion.so/my-integrations |
NOTION_PARENT_PAGE_ID | Page ID where databases will be created | Copy from Notion page URL (32-char ID) |
Create Notion integration
Go to notion.so/my-integrations, create a new integration, and copy the API key.
Share parent page with integration
In Notion, open the parent page, click “Share”, and invite your integration.
Invocation
Modes of operation
Mode 1: Push (Local → Notion) — Default
Push all local artifacts to Notion databases.- Creates/verifies 9 Notion databases (REQ, UC, WF, API, BDD, INV, ADR, TASK, Pipeline Status)
- Upserts all artifacts as Notion pages with properties
- Creates Notion relations between pages (UC → REQ, BDD → UC, etc.)
- Updates sync state (
.sdd-notion-sync.json) - Idempotent: running multiple times doesn’t create duplicates
Mode 2: Pull (Notion → Local)
Detect changes made in Notion and apply them to local markdown files.- Queries each database for pages modified after
lastSync - Compares Notion property values against local artifacts
- Classifies changes as:
notion-ahead,conflict, orsynced - Presents changes for user confirmation before applying
- Applies confirmed changes to local markdown files
- Marks affected pipeline stages as
staleinpipeline-state.json - Handles conflicts: presents both versions for user decision
Mode 3: Status
Show sync state without making changes.- Last sync timestamp and direction
- Drift detection: local changes since last push, Notion changes since last sync
- Database integrity: missing databases, orphaned pages
How it works
Step 1: Verify authentication
- Check that
NOTION_API_KEYandNOTION_PARENT_PAGE_IDare set - Verify API key works via
GET /v1/users/me - If authentication fails, show setup instructions
Step 2: Load traceability graph
Readdashboard/traceability-graph.json.
- If missing: inform user to run
/sdd:dashboardfirst - Extract all artifacts and relationships
Step 3: Load sync state
Read.sdd-notion-sync.json from project root.
- If missing: this is a fresh sync (all artifacts are
new-local) - If exists: load previous database IDs and page mappings
Step 4: Create/verify databases (Push mode)
For each artifact type that has artifacts, ensure a Notion database exists:- Check if database ID from sync state is still valid via
GET /v1/databases/{id} - If missing or deleted, create new database under parent page using schema from
references/notion-schema.md - Update sync state with database IDs
- Requirements DB
- Use Cases DB
- Workflows DB
- API Contracts DB
- BDD Scenarios DB
- Invariants DB
- ADR DB
- Tasks DB
- Pipeline Status DB
Step 5: Upsert artifacts (Push mode)
For each artifact in the traceability graph:- Check sync state for existing Notion page
- If new: CREATE page via
POST /v1/pages - If exists and local content changed (hash mismatch): UPDATE page via
PATCH /v1/pages/{id} - If exists and unchanged: SKIP
Step 6: Create relations (Push mode)
After all pages are created, create Notion relations:- For each relationship in the graph, look up source and target Notion page IDs
- Update source page’s relation property to include target
- Skip relations where either page doesn’t exist in Notion
Step 7: Detect Notion changes (Pull mode)
Query each database for pages modified afterlastSync:
- For each changed page, compare property values against local artifact
- Classify changes as:
notion-ahead,conflict, orsynced - Present changes to user for confirmation before applying
Step 8: Apply changes (Pull mode, with confirmation)
For confirmed changes:- Locate the local markdown file and line number
- Apply the change (title update, priority change, etc.)
- Mark affected pipeline stages as
staleinpipeline-state.json
Step 9: Update sync state
Write updated.sdd-notion-sync.json with:
- New
lastSynctimestamp - Updated page IDs and hashes
- Direction of last sync
Step 10: Report summary
Notion database schema
Each artifact type maps to a Notion database with specific properties:Requirements DB
- Title: REQ-ID
- Category: Select (FUN, NFR, OPS, REG, DER)
- Priority: Select (Must Have, Should Have, Could Have)
- EARS Statement: Rich text
- Acceptance Criteria: Rich text (Gherkin)
- Traceability: Relation to Use Cases DB
- Status: Formula (coverage calculation)
Use Cases DB
- Title: UC-ID
- Name: Text
- Actor: Text
- Implements: Relation to Requirements DB
- Verified By: Relation to BDD Scenarios DB
- Complexity: Select (Low, Medium, High)
Tasks DB
- Title: TASK-ID
- FASE: Number
- Type: Select (setup, feature, test, refactor, doc)
- Status: Checkbox (completed)
- Implements: Relation to Use Cases DB
- Commit SHA: Text
- Files Changed: Number
Constraints
- Never store API keys: Do not write
NOTION_API_KEYto any file. Read from environment only. - Rate limiting: Always respect Notion’s 3 req/s limit with 350ms delays.
- Confirmation for pulls: Never auto-apply Notion → Local changes without user confirmation.
- Never auto-delete: If an artifact is deleted in Notion, flag it for user review rather than deleting locally.
- Idempotent pushes: Running push multiple times should not create duplicate pages.
- JSON escape: Properly escape special characters in artifact titles when building API payloads.
Example workflows
Initial push
Stakeholder edits in Notion
Regular sync cycle
Related skills
Dashboard
Generate traceability graph (prerequisite)
Requirements Change
Apply pulled changes systematically
Pipeline Status
Check what needs re-execution after pull