Smithery Logo
MCPsSkillsDocsPricing
Login
Smithery Logo

Accelerating the Agent Economy

Resources

DocumentationPrivacy PolicySystem Status

Company

PricingAboutBlog

Connect

© 2026 Smithery. All rights reserved.

    DidierRLopes

    convert-beehiiv-newsletter

    DidierRLopes/convert-beehiiv-newsletter
    Writing
    6

    About

    SKILL.md

    Install

    Install via Skills CLI

    or add to your agent
    • Claude Code
      Claude Code
    • Codex
      Codex
    • OpenClaw
      OpenClaw
    • Cursor
      Cursor
    • Amp
      Amp
    • GitHub Copilot
      GitHub Copilot
    • Gemini CLI
      Gemini CLI
    • Kilo Code
      Kilo Code
    • Junie
      Junie
    • Replit
      Replit
    • Windsurf
      Windsurf
    • Cline
      Cline
    • Continue
      Continue
    • OpenCode
      OpenCode
    • OpenHands
      OpenHands
    • Roo Code
      Roo Code
    • Augment
      Augment
    • Goose
      Goose
    • Trae
      Trae
    • Zencoder
      Zencoder
    • Antigravity
      Antigravity
    ├─
    ├─
    └─

    About

    Converts Beehiiv newsletter posts into properly formatted blog markdown files. Use when converting newsletters to blog posts, importing Beehiiv content, or creating blog posts from newsletter URLs.

    SKILL.md

    Converting Newsletter to Blog Post

    A comprehensive guide for converting Substack (or Beehiiv) newsletter posts into properly formatted blog markdown files for the website.

    Supported Platforms

    • Substack (primary): https://didierrlopes.substack.com/p/<slug> or https://substack.com/home/post/p-<id>
    • Beehiiv (legacy): https://didierlopes.beehiiv.com/p/<slug>

    Prerequisites

    • Access to the newsletter URL
    • Image extraction capabilities (use mcp__fetch__imageFetch tool)
    • Understanding of the blog's markdown structure and front matter requirements

    Step-by-Step Conversion Process

    1. Extract Newsletter Content

    Use the imageFetch tool to extract content and images:

    mcp__fetch__imageFetch with url=<newsletter-url> and images={"output": "file", "layout": "individual", "maxCount": 10}
    

    Platform-specific notes:

    Substack:

    • Content is usually well-extracted via imageFetch in markdown mode
    • For posts accessed via substack.com/home/post/p-<id>, the content may be embedded in JSON within the HTML. Use raw=true and extract the body_html field from the embedded JSON
    • Clean Substack tracking params: remove ?utm_source=didierlopes.beehiiv.com&utm_medium=newsletter&utm_campaign=... from URLs
    • Substack image URLs follow the pattern: https://substackcdn.com/image/fetch/.../https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F<uuid>_<dimensions>.<ext>
    • To download high-res images, construct URL: https://substackcdn.com/image/fetch/w_1200,c_limit,f_png,q_auto:good/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F<uuid>_<dimensions>.<ext>

    Beehiiv:

    • Content is directly extractable via imageFetch
    • Beehiiv CDN image URLs may expire, so download immediately

    Key extraction requirements:

    • Capture all text content including headings, paragraphs, and lists
    • Extract all images in high quality (minimum 1000px width)
    • Preserve link URLs and their context
    • Note any special formatting (bold, italics, quotes)
    • CRITICAL: The blog post content must be 1:1 with the original newsletter (excluding ads). Do not summarize, paraphrase, or restructure. Copy the exact content, structure, and formatting.
    • IMPORTANT: Use WebFetch with a prompt to extract ALL important links:
      • GitHub repository URLs (especially for open source project posts)
      • YouTube video URLs (these need to be embedded as iframes)
      • Links to other newsletter posts (convert to internal blog links if already converted)
      • Any other substantive links mentioned in the content

    2. Get Publication Date

    Format: YYYY-MM-DD

    Substack:

    • Fetch the archive page: https://didierrlopes.substack.com/archive
    • Use raw mode and extract post titles alongside dates with pattern matching
    • Dates appear as short format (e.g., "Feb 24", "Mar 6") next to post titles
    • The slug may contain a date suffix (e.g., the-era-of-on-demand-software-26-01-31) but do NOT use it - it may not match the actual publication date
    • Always verify against the archive page

    Beehiiv:

    • Extract the publication date from https://didierlopes.beehiiv.com/ main page
    • Find the newsletter post by title and get its publication date

    Rules:

    • Never use today's date - always use the actual publication date
    • Create slug from title: lowercase, replace spaces with hyphens, remove special characters
    • Example: "The trampoline job: Optimize your career for growth" → 2025-09-19-the-trampoline-job-optimize-your-career-for-growth.md

    3. Create Front Matter

    ---
    slug: <title-slug-without-date>
    title: <Full Newsletter Title>
    date: <YYYY-MM-DD>
    image: /blog/<filename>.webp
    tags:
    - <relevant-tag-1>
    - <relevant-tag-2>
    - <relevant-tag-3>
    description: <Newsletter subtitle or first paragraph summary (max 160 chars)>
    hideSidebar: true
    ---
    

    Front Matter Rules:

    • slug: Use title in kebab-case without the date prefix
    • title: Exact newsletter title, properly capitalized
    • date: Newsletter publication date in YYYY-MM-DD format (from archive page, NOT today's date)
    • image: Points to the hero image path (WITH .webp extension). If the post has no cover image, omit this field
    • tags: Extract 3-6 relevant tags from content themes (lowercase)
    • description: Use newsletter subtitle or create compelling summary
    • hideSidebar: Set to true for blog posts

    4. Process Images

    IMPORTANT: All images must be in WebP format for optimal file size and fast page loads.

    Image Handling Rules:

    1. Hero Image

      • Substack: Fetch from the archive page (https://didierrlopes.substack.com/archive). Extract thumbnail image URLs which follow the pattern with public%2Fimages%2F<uuid>. Download at high resolution using: https://substackcdn.com/image/fetch/w_1200,c_limit,f_png,q_auto:good/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F<uuid>_<dimensions>.<ext>
      • Beehiiv: Fetch the hero image from https://didierlopes.beehiiv.com/ main page
      • Some posts may use YouTube thumbnails as cover images (URL pattern: https://substackcdn.com/image/youtube/w_728,c_limit/<video_id>)
      • Download to /static/blog/YYYY-MM-DD-slug.png (or .jpg) first, then convert to WebP
      • Note: The image must be saved in the static/blog/ directory, not just /blog/
      • If a post has no cover image at all, omit the image: field from front matter
    2. Content Images

      • Download to /static/blog/YYYY-MM-DD-slug_N.png (where N is sequential number)
      • Download from Substack/Beehiiv CDN URLs
      • Maintain aspect ratio
      • Note: Save in the static/blog/ directory
    3. Convert All Images to WebP After downloading images, convert them to WebP format using:

      # For PNG/JPG images:
      cwebp -q 90 "image.png" -o "image.webp" && rm "image.png"
      
      # For GIF images (animated):
      gif2webp -q 90 "image.gif" -o "image.webp" && rm "image.gif"
      

      Final filenames should be:

      • Hero: /static/blog/YYYY-MM-DD-slug.webp
      • Content: /static/blog/YYYY-MM-DD-slug_N.webp
    4. Image Markdown Format

      ![Alt text description](/blog/image-path.webp)
      
      <!-- For centered images with custom width -->
      <p align="center">
          <img width="500" src="/blog/image-path.webp" alt="Description" />
      </p>
      

    5. Convert Content Structure

    Content Conversion Rules:

    1. Opening Section

      • Do NOT add hero image in the content (it's handled automatically via the front matter image field)
      • Include newsletter subtitle as opening paragraph
      • Add <!-- truncate --> after intro paragraph for blog preview
    2. Section Dividers

      • Generally not needed between sections
      • Let content flow naturally without visual breaks
      • Only use if there's a major topic shift that requires clear separation
    3. Headings

      • Newsletter H3 → Blog H2 (##)
      • Newsletter H4 → Blog H3 (###)
      • Maintain heading hierarchy
    4. Lists

      • Preserve bullet points as markdown lists (-)
      • Maintain indentation for nested lists
      • Important: Add <br /> after each list block for proper spacing

      Example:

      - First item
      - Second item
      - Third item
      
      <br />
      
      Next paragraph starts here...
      
    5. Links

      • Substack: Remove tracking parameters (?utm_source=...&utm_medium=...&utm_campaign=...)
      • Beehiiv: Convert Beehiiv tracking URLs to original URLs
      • Format: [link text](url)
      • For tweets/social embeds, reference as: This [post](url)
      • Convert links to other newsletter posts to internal blog links if already converted (e.g., https://didierlopes.com/blog/<slug>)
    6. Emphasis

      • Bold text: **text**
      • Italic text: *text*
    7. Quotes and Citations

      • Use blockquote syntax (>) for extended quotes
      • For multi-paragraph quotes, use > <br /> between paragraphs
      • Add <br /> after the quote block
      • IMPORTANT: Extract the actual hyperlink from the newsletter, not guess or create new ones
      • Include attribution with author name and link when available

      Example:

      > First paragraph of the quote goes here.
      >
      > <br />
      >
      > Second paragraph of the quote continues here.
      
      <br />
      
      **Author Name** - ["Article Title"](https://actual-link.com)
      
    8. Code/Technical Content

      • Wrap technical terms in backticks: `term`
      • Use code blocks for snippets
    9. YouTube Videos

      • IMPORTANT: Extract the actual YouTube URL from the newsletter content
      • Convert YouTube links to embedded iframe format
      • Extract video ID from URL (e.g., https://www.youtube.com/watch?v=VIDEO_ID → VIDEO_ID)
      • Use only the video ID in the embed URL, no additional parameters
      • Use responsive embed with centered layout
      • IMPORTANT: Add <br /> after the video embed so following text doesn't appear glued to it

      Example conversion:

      • Original: https://www.youtube.com/watch?v=Zyw-YA0k3xo
      • Embed format:
      <div className="flex place-items-center justify-center items-center rounded-sm mx-auto">
          <iframe
              src="https://www.youtube.com/embed/Zyw-YA0k3xo"
              width="800"
              height="400"
          />
      </div>
      
      <br />
      

      Note: Always verify the video link exists in the original content - don't assume or guess video IDs

    10. Image Captions

      • If text immediately following an image is a caption/description of that image, style it differently
      • Use smaller font size and bring it closer to the image with negative margin

      Example:

      <p align="center">
          <img width="800" src="/blog/image.webp" alt="Description" />
      </p>
      <p align="center" style={{fontSize: '0.85em', marginTop: '-0.5em'}}>Caption text describing the image above.</p>
      

    6. Content Cleanup

    Remove from Newsletter:

    • Footer/unsubscribe links
    • Newsletter-specific CTAs (subscribe buttons, share widgets)
    • Tracking parameters from URLs (?utm_source=...)
    • Newsletter metadata (view in browser links)
    • Substack "No posts" artifacts at the bottom
    • "A quick note: I've moved this newsletter from Beehiiv to Substack" migration notices (unless contextually important)

    Preserve:

    • Author voice and tone
    • All substantive content
    • External references and citations
    • Story flow and narrative structure

    7. Quality Checks

    Before finalizing:

    • Front matter is complete and valid YAML
    • Front matter image: field includes .webp extension (or is omitted if no cover image)
    • All images are downloaded, converted to WebP, and properly referenced
    • All image references in content use .webp extension
    • Links are clean (no tracking parameters)
    • Markdown syntax is valid
    • Content flows naturally without newsletter artifacts
    • File is saved in /blog/ directory with correct naming
    • Test render locally to ensure formatting

    Example Conversions

    Substack URL: https://didierrlopes.substack.com/p/the-context-wars-in-financial-services Converted to: /blog/2026-02-13-the-context-wars-in-financial-services.md

    Beehiiv URL: https://didierlopes.beehiiv.com/p/the-trampoline-job-optimize-your-career-for-growth Converted to: /blog/2025-09-19-the-trampoline-job-optimize-your-career-for-growth.md

    Key transformations:

    • Extracted images and converted to WebP
    • Converted newsletter sections to H2/H3 headings
    • Cleaned URLs of tracking parameters
    • Added proper front matter with relevant tags
    • Preserved personal narrative and bullet points

    Common Pitfalls to Avoid

    • Don't include newsletter-specific language ("Click here to read more")
    • Don't forget to download images (CDN links may expire)
    • Don't use relative dates ("last week") - use specific dates
    • Don't include email-specific formatting (table layouts for email clients)
    • Don't forget the <!-- truncate --> marker for blog preview
    • Don't trust date suffixes in Substack slugs - always verify against the archive page
    • Don't use substack.com/home/post/p-<id> URLs directly for content extraction - try didierrlopes.substack.com/p/<slug> first as it renders better
    Recommended Servers
    Docfork
    Docfork
    Confluence
    Confluence
    ScrapeGraph AI Integration Server
    ScrapeGraph AI Integration Server
    Repository
    didierrlopes/my-website
    Files