I publish content on two platforms: a static website (Cloudflare Pages) and Dev.to, the developer community platform. Publishing the same article to both used to take 15-20 minutes of manual work. Now it takes one command.

Here's exactly how I built it.

The Problem

Every article needed:

  1. HTML conversion (Markdown → styled HTML)
  2. 2. Website deployment (upload to Cloudflare Pages via Wrangler)

    3. Cross-posting to Dev.to (log into their editor, paste content, format images, set cover image)

    4. Index updates (add new article to the homepage list)

    Step 3 alone took 10+ minutes because each platform's rich text editor reformats your carefully crafted HTML differently.

    The Solution: A Single Publish Script

    I wrote a Python script that does all of this in one command:

    
    python3 scripts/publish.py articles/my-new-post.md --theme ocean-calm
    

    Architecture

    
    ┌─────────────────┐     ┌──────────────────┐     ┌───────────────────┐
    │  Markdown file   │────▶│  build.py         │────▶│  site/ (HTML)     │
    │  articles/*.md   │     │  (MD→HTML+Index)  │     │  static files     │
    └─────────────────┘     └──────────────────┘     └───────────────────┘
                                                            │
                                                  ┌─────────┼─────────┐
                                                  ▼                   ▼
                                       ┌────────────────┐   ┌────────────────┐
                                       │ Cloudflare      │   │ Dev.to          │
                                       │ Pages (wrangler)│   │ (API cross-post)│
                                       └────────────────┘   └────────────────┘
    

    Step 1: Markdown → HTML

    
    def build_article(md_file):
        meta, content = parse_md(md_file)
        body_html = md_to_html(content)
        
        # Generate ToC from headings
        toc = extract_headings(content)
        
        # Build complete HTML from template
        html = template.replace('{{TITLE}}', meta['title'])
                       .replace('{{CONTENT}}', body_html)
                       .replace('{{TOC}}', toc)
        
        # Write article HTML
        slug = os.path.splitext(os.path.basename(md_file))[0]
        with open(f'site/articles/{slug}.html', 'w') as f:
            f.write(html)
    

    Step 2: Deploy to Cloudflare Pages

    
    npx wrangler pages deploy site --project-name=my-site
    

    Cloudflare Pages handles the rest — CDN, HTTPS, custom domain. The deployment takes about 10 seconds.

    Step 3: Cross-post to Dev.to

    Dev.to provides a clean REST API for creating articles as a user:

    
    def publish_to_devto(title, body_html, tags, cover_image):
        article_data = {
            "article": {
                "title": title,
                "body_markdown": convert_html_to_markdown(body_html),
                "tags": tags,
                "main_image": cover_image,
                "published": True,
                "canonical_url": f"https://mysite.com/articles/{slug}"
            }
        }
        
        resp = requests.post(
            "https://dev.to/api/articles",
            headers={"api-key": os.environ["DEVTO_API_KEY"]},
            json=article_data
        )
    

    The key was including a `canonical_url` pointing to your own site — this tells search engines your site is the original source, not Dev.to, which preserves your SEO while still getting the cross-posting reach.

    Results

    | Metric | Before | After | Improvement |

    |--------|--------|-------|-------------|

    | Time per article | 15-20 min | ~2 min | 85% faster |

    | Steps | 8 manual steps | 1 command | 7 fewer steps |

    | Error rate | ~20% (forgot a step) | <1% | Consistent |

    Lessons Learned

    1. **Start with the bottleneck** — I automated the cross-posting step first because it was the most tedious. Everything else was a bonus.
    2. 2. API-first where possible — CLI tools and APIs are easier to automate than browser-based interfaces. Dev.to's REST API made this trivial.

      3. Idempotency matters — My script can safely re-run without creating duplicate posts. It checks if an article with the same title already exists before creating.

      4. Set canonical URLs — When cross-posting to community platforms, always set the canonical URL to your own site. This protects your SEO while still getting distribution.

      The Script

      The complete publish script is about 200 lines of Python. The structure is simple enough that you could adapt it to any static site + community platform (Medium, Hashnode, Substack all have similar APIs).

      The core principle: if you do it more than twice, script it.

      Verdict

      This pipeline has been running for months without issues. The initial investment of about 3 hours to build it has saved me countless hours since. Every content creator should have something similar — it removes the friction between "I wrote something" and "it's published."