| name | publish-to-notion |
| description | Converts an HTML audit deliverable into a Notion page, applying all the Notion-specific formatting rules from PLAYBOOK §11b. Use when the user asks to "publish to Notion", "push this to Notion", or "mirror the audit into Notion". |
publish-to-notion
Mirrors an HTML audit into Notion. This is where most past mistakes happened — follow the rules strictly.
Preconditions
- Notion MCP is available (
mcp__*__notion-create-pages et al.).
- Every image in the HTML has a public URL (invoke
upload-image first if not).
- User has specified a parent page or teamspace. If they give a teamspace ID, warn them that teamspace IDs are not valid parents — find or create a specific page inside it instead.
Hard rules (PLAYBOOK §11b)
-
Tables: one row per line, tabs for indentation, fit-page-width="true" on every findings table:
<table header-row="true" fit-page-width="true">
<tr>
<td>cell</td>
<td>cell</td>
</tr>
<tr>
<td>cell</td>
<td>cell</td>
</tr>
</table>
Single-line table HTML parses as one mega-row. Never compress.
-
Flow diagrams: PNG only. Never paste Mermaid. Use flow-diagram skill to produce PNG, then upload-image.
-
Images: public URLs only. Verify Content-Length > 0 before embedding.
-
Callouts: don't anchor update_content inside a callout — new content gets nested. Use replace_content for structural edits.
-
Full-width: API can't set it. Tell the user to toggle "Full width" manually via ··· menu after the page is created.
-
is_full_width and similar properties: API accepts them silently but they have no effect. Don't rely on them.
Procedure
- Read the source HTML (
*.html).
- Build Notion content as markdown-with-HTML-tables. Sections follow the HTML structure:
- H1 title from
<header.doc-head h1>.
- Meta grid → bullet list at the top.
- Each
<section class="screen"> → H2 heading + findings table + priorities callout.
- Master list → one big
<table>.
- For every
<img>: replace the local src with the uploaded URL.
- Create the page with
notion-create-pages. If the parent is a workspace, create as private page (no parent) and ask the user to move it.
- After creation, tell the user:
- Page URL.
- To toggle Full width manually.
- To verify every image loaded (0-byte uploads break silently on catbox).
Validation
After publish:
- Fetch the page back with
notion-fetch.
- Grep the returned body for "0 bytes" or
https://files.catbox.moe/ links → spot-check each loads.
- Confirm table rows are not merged into one mega-row (compare row count to HTML source).
- If a structural fix is needed: use
replace_content with the full new body, not incremental update_content.