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.

설치로 이동

소스 정보

저장소
DidierRLopes/my-website
최근 소스 활동
2026년 6월 22일 23:20
감지된 SKILL.md 언어
영어
스타
8
포크
1

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
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
GitHub에서 보기