Skip to main content

convert-newsletter

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

Aller à l'installation

Informations de source

Dépôt
DidierRLopes/my-website
Dernière activité de la source
22 juin 2026 à 23:20
Langue détectée de SKILL.md
anglais
Étoiles
8
Forks
1

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
name
convert-newsletter
description
Converts Substack (or Beehiiv) newsletter posts into properly formatted blog markdown files. Use when converting newsletters to blog posts, importing Substack/Beehiiv content, or creating blog posts from newsletter URLs.
allowed-tools
["Read","Write","Bash","Glob","Grep","mcp__fetch__imageFetch","WebFetch"]
# 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 ```yaml --- slug: <title-slug-without-date> title: <Full Newsletter Title> date: <YYYY-MM-DD> image: /blog/YYYY-MM-DD-slug/hero.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 inside the post asset folder (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/hero.png` (or `.jpg`) first, then convert to WebP - Note: The image must be saved in the post's `static/blog/YYYY-MM-DD-slug/` 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 post's `static/blog/YYYY-MM-DD-slug/` directory 3. **Convert All Images to WebP** After downloading images, convert them to WebP format using: ```bash # 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/hero.webp` - Content: `/static/blog/YYYY-MM-DD-slug/N.webp` 4. **Image Markdown Format** ```markdown ![Alt text description](/blog/YYYY-MM-DD-slug/image-path.webp) <!-- For centered images with custom width --> <p align="center"> <img width="500" src="/blog/YYYY-MM-DD-slug/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: ```markdown - 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: ```markdown > 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: ```html <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: ```html <p align="center"> <img width="800" src="/blog/YYYY-MM-DD-slug/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
Voir sur GitHub