Convert JJude blog posts into 3-format social media content (post/tweet/thread) with reuse tracking.
Convert Joseph Jude's blog posts into three social media formats, stored in a single reusable file per post.
| Format | Length | Platforms |
|---|---|---|
| Post | 100-150 words | LinkedIn, Twitter |
| Tweet | ≤300 chars | Bsky, Mastodon, Threads |
| Thread | Multi-tweet, each ≤300 chars | Twitter, Bsky |
All social media content (both jjude.com and CTO Field Notes) lives in ONE centralized directory. The url field in frontmatter identifies the publication.
produce/hermes/social-media/
├── content/ # One file per blog post (both publications)
│ ├── weekly-review.md # jjude.com
│ ├── engineering-mind.md # CTO Field Notes
│ ├── flywheel.md
│ └── ...
├── published/
│ └── log.csv # Publishing tracking
├── images/
│ ├── diagrams/ # Excalidraw sources
│ └── generated/ # PNGs, prompts, style guides
├── _meta/
│ ├── templates/ # post.md, tweet.md, thread.md
│ └── prompts/ # generation-prompt.md
└── sources.csv
Do NOT create per-publication social-media directories. Keep everything in this one place.
Each blog post gets ONE file with all three formats:
---
title: "Blog Post Title"
url: https://jjude.com/slug/
slug: blog-slug
tier: evergreen | recent
created: YYYY-MM-DD
last_used: YYYY-MM-DD
next_use: YYYY-MM-DD
Post (LinkedIn, Twitter)
[100-150 word post]
Tweet (Bsky, Mastodon, Threads)
[≤300 char tweet]
Thread (Twitter, Bsky)
[first tweet]
[second tweet]
[third tweet]
blogging skill first. All voice rules (I-voice, banned words, Flesch 65-70, ASD-STE100) come from there. This section only adds social-specific deltas:
1. Read the source blog post (from URL or wiki)
2. Identify the ONE sharpest insight — the idea worth sharing
3. Find a personal angle (what Joseph learned, tried, or observed)
4. Generate all 3 formats:
5. Save as content/{slug}.md with metadata
6. Show Joseph for review before any publishing
When Joseph says "post {slug}" or similar:
1. Read content/{slug}.md
2. Build variants.json for Typefully (see typefully-pipeline skill)
3. Run create_drafts.py once per format — the script creates one draft per run. For three formats (LinkedIn post, tweet, thread), create three separate spec files and run the script three times. Save specs to /opt/data/variants-{slug}-{format}.json (not /tmp/).
4. Collect the Typefully draft URLs from each run
5. Update last_used and next_use (3-6 months out) in the content file
6. Tell Joseph the drafts are ready with all URLs
When Joseph requests changes:
1. Read content/{slug}.md
2. Make the requested edits
3. Show Joseph the updated content
4. Save back to file
evergreen (repost anytime) or recent (time-sensitive)| Format | Platforms |
|---|---|
| Post | LinkedIn, Twitter |
| Tweet | Bsky, Mastodon, Threads |
| Thread | Twitter, Bsky |
1. Post length creep: Posts drift toward 250+ words. Trim ruthlessly — 100-150 words is the target.
2. Thread tweet independence: Each tweet in a thread must work as a standalone quote. No "building on the previous point..."
3. Bsky char limit: Max 300 chars per post. Thread tweets must each be under 300.
4. No emoji in Excalidraw: If adding diagrams, Excalidraw's Virgil font doesn't render emoji.
5. Template drift: When generating at scale, posts can converge on a formula. Vary hooks (story, question, counterintuitive claim, personal anecdote).
6. Reuse check: Before posting, verify the content is still relevant. Don't repost outdated references.
7. Slug resolution: Blog filenames have full titles, not slugs. Read YAML frontmatter slug field to match.
8. No /tmp writes: HERMES_WRITE_SAFE_ROOT=/opt/data blocks writes to /tmp. Save temp files (like variants.json) to /opt/data/ instead, e.g. /opt/data/variants-{slug}.json. Clean up after use.