Transform long-form content into platform-specific short-form posts using Claude API.
Paste a YouTube URL, blog article, or raw text — get content for 12 platforms streamed back in real time.
- 3 input types — YouTube videos (transcript extraction), article URLs (web scraping), pasted text
- 12 output formats — Twitter/X, LinkedIn, Instagram, TikTok, Newsletter, Facebook, Reddit, Threads, Pinterest, YouTube, Bluesky, Reels
- Batch mode — Tick any subset of platforms, generate them all in parallel against a single extraction
- Prompt caching — Source content cached on first call; subsequent platforms in the same batch hit cache (~5 min TTL)
- Per-card streaming — Each selected platform gets its own card with live SSE output, copy button, and status badge
- Copy-all — Concatenate every output into one clipboard payload, separated by platform headers — drop straight into a client deliverable
- Selection memory — Your last platform picks persist in localStorage across sessions
- Dark/light mode — Toggle with localStorage persistence
git clone https://github.com/Morton26-ops/content-repurposer.git
cd content-repurposer
pip install -r requirements.txt
cp .env.example .env
# Add your API key to .env
uvicorn main:app --reloadGet one at console.anthropic.com. Add it to .env:
ANTHROPIC_API_KEY=sk-ant-...
content-repurposer/
├── main.py # FastAPI app — GET /, POST /extract, POST /generate (SSE)
├── config.py # Settings via pydantic-settings + .env
├── extractors.py # YouTube transcript, URL scraping, text passthrough
├── prompts.py # Platform rules + cached system-block builder
├── generator.py # Claude async streaming + prompt caching
├── requirements.txt
├── .env.example
├── templates/
│ └── index.html # Single-page UI
└── static/
├── style.css
└── app.js # Batch dispatch, SSE consumption, per-card rendering
- User picks an input type, pastes content, and ticks one or more platforms
- Frontend
POST /extractonce → server fetches/scrapes/passes-through, returns the text - Frontend
POST /generatein parallel, once per selected platform, with the same extracted text - Source content rides in the
system=parameter withcache_control: ephemeral; the 2nd…Nth calls in the batch hit cache for the heavy prefix and only pay for the small per-platform rules block - Each platform's response streams back via SSE into its own result card with a live cursor and per-card copy button
| Platform | Rules |
|---|---|
| Twitter/X | 3-10 tweets, 280 chars each, numbered, hook first |
| 1000-1300 chars, hook line, short paragraphs, 3-5 hashtags | |
| <300 char body, CTA, 15-25 hashtags | |
| TikTok | 150-300 word script, hook + [PAUSE] markers, 60-90 sec |
| Newsletter | 400-600 words, subject line, bold section headers, key takeaway |
| 500-800 chars, storytelling hook, question CTA, 1-3 hashtags | |
| Title + 300-600 word body, authentic tone, TL;DR, no emojis | |
| Threads | 3-7 posts, <500 chars each, casual tone, no hashtags |
| 200-500 chars, SEO keywords, save/click CTA | |
| YouTube | Description + timestamps + key takeaways, 5-10 tags |
| Bluesky | 3-8 posts, 300 chars each, witty/intellectual tone |
| Reels | 100-200 word script, [CUT] + [TEXT ON SCREEN] markers, 30-60 sec |
- Backend: FastAPI + Jinja2 + sse-starlette
- AI: Claude API (claude-opus-4-7) with async streaming + prompt caching
- Extraction: youtube-transcript-api, BeautifulSoup, requests
- Config: pydantic-settings + python-dotenv
