Sync to notion doc
AI operating system for product managers. 65 Claude Code skills, 7 multi-perspective review agents, a memory system. Battle-tested in real PM work.
npx -y skills add talgacapri/pm-os --skill sync-to-notion-docAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Sync finalized Markdown documents from PM-OS to the Notion Documentation DB. Detects, classifies, converts, and pushes MD files as properly formatted Notion pages.
SKILL.md
11.6 KB, ~3.0k tokens by cl100k_base, as published. Nobody here has run it
Quick Start
/sync-to-notion → Scan notion-docs/ for unsynced files
/sync-to-notion notion-docs/my-doc.md → Sync a specific file from the staging folder
/sync-to-notion outputs/launches/alpha-plan.md → Sync a file directly from outputs
What you get: A Notion page in the Documentation DB with the correct Document Type, formatted content, and a sync record in the local file's YAML frontmatter.
Sync target: Notion Documentation DB at https://www.notion.so/Docs-2176409321d9814b8107ea8f9943e76f
- Data source ID:
21764093-21d9-81a8-baca-000b9e5d9228
Time: 1-2 minutes per document.
/sync-to-notion - Notion Document Sync
Purpose
Push finalized Markdown documents from PM-OS to the Notion Documentation DB as properly formatted pages. Supports both new page creation and updates to previously synced pages.
Invocation Patterns
This skill supports three invocation styles:
- Explicit file path:
/sync-to-notion path/to/file.mdsyncs a single specific file. - Folder scan:
/sync-to-notion-doc(no arguments) scansnotion-docs/for any MD files that have not been synced yet (nonotion_page_idin their YAML frontmatter). - Post-workflow prompt: After any PM-OS skill creates a file in
outputs/, offer: "Want me to push this to Notion?"
Workflow
Step 1: Detect and Read the MD File
If a file path is provided:
- Read the file at the given path.
- If it does not exist, tell the user and stop.
If no file path is provided (folder scan):
- List all
.mdfiles innotion-docs/(excludingREADME.md). - For each file, check the YAML frontmatter for a
notion_page_idfield. - Files without
notion_page_idare unsynced. Present the list and ask the user which ones to sync (or sync all). - If no unsynced files exist, tell the user and stop.
Check for existing sync record:
- If the file already has
notion_page_idin its YAML frontmatter, this is an update, not a create. Note thenotion_page_idfor Step 5.
Step 2: Classify the Document Type
Map the file to one of the Notion Documentation DB's Document Type values by analyzing the file's source path and content.
Classification rules (in priority order):
| Signal | Document Type |
|---|---|
Path contains prds/ or content has PRD structure (hypothesis, success metrics, rollout) | PRD |
Path contains launches/ or content has launch/testing/checklist structure | Specification |
Path contains research-synthesis/ or research/ or content is user research | User Research |
Path contains decisions/ or content has decision log structure | Discovery |
Path contains strategy/ or content is strategy, OKR, roadmap | Strategy |
| Content describes a process, SOP, or operational procedure | Standard Operating Procedure (SOP) |
| Content is a policy, privacy doc, compliance, or regulatory | Policy |
| Content is a technical standard, API spec, or engineering standard | Standard |
| None of the above | Ask the user to choose |
Always confirm the classification with the user before proceeding. Present it as:
I've classified this as [Document Type]. Does that look right, or would you prefer a different type?
Options: Specification, Discovery, PRD, Policy, Standard, Standard Operating Procedure (SOP), Strategy, User Research
Step 3: Set Document Status
Default to "Draft" unless the user specifies otherwise.
Ask: "Document status? Default is Draft."
Valid values: Draft, Dev Review, Approved for Dev, In Dev, In Production, Archived
Step 4: Convert MD to Notion-Flavored Markdown
Before converting, fetch the Enhanced Markdown Specification to get the exact syntax:
FetchMcpResource: server=user-Notion, uri=notion://docs/enhanced-markdown-spec
Conversion rules:
-
Strip YAML frontmatter. Remove any existing
---delimited YAML block from the top of the file. The frontmatter is metadata for PM-OS, not Notion content. -
Extract the document title. Use the first
# Headingin the document as theNameproperty. Remove it from the body content (Notion shows the title separately above the page content). -
Convert standard Markdown tables to Notion table format. Standard Markdown tables (
| col1 | col2 |) must be converted to Notion's XML table format:<table header-row="true"> <tr> <td>Header 1</td> <td>Header 2</td> </tr> <tr> <td>Cell 1</td> <td>Cell 2</td> </tr> </table> -
Preserve code blocks as-is. Notion supports standard fenced code blocks. Do NOT escape special characters inside code blocks.
-
Convert horizontal rules. Standard
---becomes a Notion divider (same syntax, but make sure it is on its own line with blank lines around it). -
Preserve headings, lists, bold, italic, strikethrough, links, and inline code. These are compatible between standard Markdown and Notion-flavored Markdown.
-
Convert checkboxes.
- [ ]and- [x]are natively supported. -
Strip any HTML that Notion does not support. If the source MD contains raw HTML (e.g.,
<br>,<div>), convert<br>to Notion's<br>(same), and strip unsupported tags. -
Do NOT include the page title in the body content. The title goes into the
Nameproperty only.
Step 5: Create or Update the Page in Notion
For new pages (no existing notion_page_id):
Use CallMcpTool with notion-create-pages:
{
"server": "user-Notion",
"toolName": "notion-create-pages",
"arguments": {
"parent": {
"data_source_id": "21764093-21d9-81a8-baca-000b9e5d9228"
},
"pages": [
{
"properties": {
"Name": "<document title>",
"Document Type": "<classified type>",
"Document Status": "<status, default Draft>"
},
"content": "<converted Notion-flavored markdown body>"
}
]
}
}
For updates (existing notion_page_id in frontmatter):
Use CallMcpTool with notion-update-page:
{
"server": "user-Notion",
"toolName": "notion-update-page",
"arguments": {
"page_id": "<notion_page_id from frontmatter>",
"command": "replace_content",
"new_str": "<converted Notion-flavored markdown body>"
}
}
Then update properties if they changed:
{
"server": "user-Notion",
"toolName": "notion-update-page",
"arguments": {
"page_id": "<notion_page_id from frontmatter>",
"command": "update_properties",
"properties": {
"Name": "<document title>",
"Document Type": "<classified type>",
"Document Status": "<status>"
}
}
}
Step 6: Record the Sync
After a successful push, update the local MD file's YAML frontmatter.
If the file has no frontmatter yet, add one at the top:
---
notion_page_id: "<page ID returned by Notion>"
notion_url: "<Notion page URL>"
document_type: "<classified type>"
synced_at: "<ISO 8601 timestamp>"
---
If the file already has frontmatter, update these fields:
notion_page_id- keep the same (or set for first sync)notion_url- keep the same (or set for first sync)document_type- update if changedsynced_at- update to current timestamp
This frontmatter is what enables idempotent syncs. On the next /sync-to-notion-doc run, the skill detects the notion_page_id and updates instead of creating a duplicate.
Step 7: Confirm to User
After a successful sync, report:
Synced to Notion.
- Page: Document Title
- Type: Document Type
- Status: Document Status
- Action: Created new page / Updated existing page
If multiple files were synced (folder scan), provide a summary table.
Error Handling
| Error | Action |
|---|---|
| File not found | Tell the user the path does not exist |
| Notion MCP not connected | Tell the user to run /connect-mcps connect to notion |
| Notion API error on create | Show the error, suggest checking the Notion workspace permissions |
| Notion API error on update (page not found) | The page may have been deleted in Notion. Ask the user if they want to create a new page instead. Remove the stale notion_page_id from frontmatter. |
| File has no content (empty) | Tell the user the file is empty and skip |
Duplicate Prevention
The skill uses notion_page_id in the local file's YAML frontmatter as the single source of truth for sync state.
- No
notion_page_id= new page, usenotion-create-pages - Has
notion_page_id= existing page, usenotion-update-page
Before creating a new page, optionally search Notion for a page with the same title to warn about potential duplicates:
{
"server": "user-Notion",
"toolName": "notion-search",
"arguments": {
"query": "<document title>",
"data_source_url": "collection://21764093-21d9-81a8-baca-000b9e5d9228"
}
}
If a match is found, ask: "A page with this title already exists in Notion. Do you want to update it or create a new one?"
Notion Documentation DB Schema Reference
The target database uses this schema:
| Property | Type | Values |
|---|---|---|
| Name | title | Document name (from first H1) |
| Document Type | select | Specification, Discovery, PRD, Policy, Standard, Standard Operating Procedure (SOP), Strategy, User Research |
| Document Status | select | Draft, Dev Review, Approved for Dev, In Dev, In Production, Archived |
| Product Lead | person | (optional, set manually in Notion) |
| Engineering Lead | person | (optional, set manually in Notion) |
| UX Lead | person | (optional, set manually in Notion) |
| GTM Lead | person | (optional, set manually in Notion) |
| Owner | person | (optional, set manually in Notion) |
| Author | person | (optional, set manually in Notion) |
| Document Version (1) | text | (optional, can be set if version info is in frontmatter) |
Person fields require Notion user IDs and cannot be set from Markdown content. They should be assigned manually in Notion after sync.
Integration with Other Skills
This skill works with every skill that creates files in outputs/:
/prd-draftcreates files inoutputs/prds/-> classify as PRD/launch-checklistcreates files inoutputs/launches/-> classify as Specification/user-research-synthesiscreates files inoutputs/research-synthesis/-> classify as User Research/decision-doccreates files inoutputs/decisions/-> classify as Discovery/write-prod-strategycreates files inoutputs/roadmaps/or strategy docs -> classify as Strategy/status-updatecreates files inoutputs/status-updates/-> classify as Specification
After any of these skills completes, the assistant can offer: "Want me to push this to Notion?"
The user can either:
- Say yes to sync immediately from
outputs/. - Move the file to
notion-docs/first and sync later.
Notion-Flavored Markdown Quick Reference
For the complete spec, always fetch: notion://docs/enhanced-markdown-spec
Key differences from standard Markdown:
- Tables use XML (
<table>,<tr>,<td>) not pipe syntax - Toggles use
<details>/<summary> - Callouts use
<callout icon="emoji"> - Colors use
{color="Color"}attribute on blocks or<span color="Color">for inline - Empty lines need
<empty-block/>(blank lines are stripped) - Indentation uses tabs, not spaces
- Page title goes in properties, not in page content