Review Medium import formatting
Run after medium_import (draft) when cross-posting from DEV.to or other markdown sources. DEV.to → Medium import often breaks code fences, splits blocks, or leaves raw markdown.
Prerequisites
publish-agentsbuilt (npm install && npm run build)- Valid Medium session (
medium-publisher session-check) - Source markdown (DEV.to body or local
.mdfile) medium_urlfrom import result (draft editor URL)
Pipeline
1. Import draft (if not done)
cd D:\code\publish-agents
npm run medium -- import --url "<public dev.to URL>" --json
Result includes medium_url, extract (blocks + flags), and screenshot path.
2. Load source markdown
- From DEV.to MCP / API:
body_markdownof the published article - Or local file used to publish DEV.to
Keep this as the ground truth for structure and code fences.
3. Compare source vs extract
Inspect extract.blocks and extract.flags:
| Check | Source (markdown) | Medium extract issue |
|---|---|---|
| Headings | # / ## / ### hierarchy |
raw_markdown_heading, wrong heading2/heading3/paragraph |
| Code fences | ```lang blocks |
empty_code_block, adjacent_code_blocks, raw_markdown_fence |
| Paragraphs | blank lines between sections | empty_paragraph |
| Bold/links | **, [text](url) |
literal ** or broken links in block text |
| Lists | - / 1. |
merged into paragraphs |
Build a fix plan: list issues → intended fix action per issue.
4. Apply fixes in editor
Use MCP medium_fix_draft or CLI:
npm run medium -- fix-draft --url "<medium_url>" --actions-file ./fixes.json --json
fixes.json example:
[
{ "type": "removeEmptyCodeBlocks" },
{ "type": "mergeAdjacentCodeBlocks" },
{ "type": "replaceBlockText", "blockIndex": 4, "text": "Section title" },
{ "type": "promoteDemoteHeading", "blockIndex": 4, "level": 2 }
]
Action reference:
removeEmptyCodeBlocks— delete emptypreblocksmergeAdjacentCodeBlocks— join consecutive code blocks (split import artifact)replaceBlockText— replace block text (headings, cleanup raw markdown)promoteDemoteHeading— set block to H2/H3/paragraph via format menu
Re-run medium_extract (or read extract from fix result) until flags are acceptable or only minor issues remain.
5. Manual fallback
If automation cannot fix a block (complex tables, embeds, images):
medium_open_draftoropen-draft --url(headed browser)- Edit manually in Medium editor
- Re-run
extractto verify
6. Confirm save — do not publish
- Fix commands wait for Medium Saved indicator
- Verify draft appears under
medium.com/me/stories - Do not call
--publishunless user explicitly asks
7. Report to user
## Medium import review
- **Draft URL:** …
- **Issues found:** …
- **Fixed:** …
- **Remaining (manual):** …
- **Extract flags:** …
MCP tools
| Tool | Purpose |
|---|---|
medium_import |
Import URL → draft + extract |
medium_extract |
Re-read editor outline |
medium_fix_draft |
Apply fix actions + autosave |
medium_open_draft |
Headed inspection |
Security checks
Before considering the draft ready:
- No accidental paste of API keys, tokens, or
.envvalues (compare suspicious blocks to source) - No
eval(/ inline secrets in code blocks that weren't in source - Links point to expected domains (no injected redirect URLs)
- Canonical/source attribution matches DEV.to URL if cross-posting
Related skills
- publish-devto-to-medium — full end-to-end pipeline (import + review + publish)
- publish-medium — login, import CLI
- publish-crosspost — DEV.to → Medium pipeline
- user-devto — fetch source markdown
Full reference: docs/devto-to-medium.md
Do not
- Publish automatically after review
- Skip comparison with source markdown
- Ignore
adjacent_code_blockson technical posts (common import bug)