🎁 Get the FREE AI Skills Starter Guide β€” Subscribe β†’
BytesAgainBytesAgain
πŸ¦€ ClawHub

Reddit Quote Carousel Topaz

by @psyduckler

Create an Instagram carousel from a popular-picks list with Reddit quotes + Topaz 2x upscaling. Cover = "clean" style ("Top CATEGORY in Destination"), attrac...

Versionv1.0.0
Downloads1,105
Installs2
TERMINAL
clawhub install reddit-quote-topaz

πŸ“– About This Skill


name: reddit-quote-topaz description: Create an Instagram carousel from a popular-picks list with Reddit quotes + Topaz 2x upscaling. Cover = "clean" style ("Top CATEGORY in Destination"), attraction slides = "quote" style with Reddit quotes + subreddit attribution. All photos Topaz-enhanced before overlay. Trigger phrase "reddit-quote-topaz". Use when Bernard says "reddit-quote-topaz" or wants a Topaz-enhanced Reddit-quote carousel.

Reddit Quote Carousel (Topaz Enhanced)

Same as reddit-quote-carousel but adds Topaz Labs 2x AI upscale after photo finding, before text overlays.

Trigger

Bernard says "reddit-quote-topaz" β†’ use this skill. Bernard says "reddit-quote" β†’ use reddit-quote-carousel (no Topaz).

Parameters

  • destination (required): City/region (e.g. "Barcelona")
  • category (required): What the picks are (e.g. "Cheap Eats", "Hidden Gems", "Date Night Spots")
  • popular_picks_url (required): tabiji.ai popular-picks page URL to pull attractions + Reddit quotes from
  • reddit_post_count (optional): Number of Reddit posts analyzed (for subtitle). Pull from the page if available.
  • Pipeline (3 chained sub-agents)

    Working directory: /tmp/ig-reddit-quote/

    Sub-agent 1: Scrape Picks + Find Photos + Topaz Enhance

    1. Fetch the popular-picks page via web_fetch to get: - List of attractions (names) - A compelling Reddit quote for each attraction (vivid, specific, personal β€” not generic praise) - The subreddit each quote came from (e.g. "r/london", "r/AskLondon") - Total Reddit post count if shown on the page

    2. Find photos using instagram-photo-find workflow: - 1 hero photo for the destination (for cover slide) - 1 photo per attraction (for quote slides) - For each: web_search β†’ download candidates β†’ vision-score β†’ keep best

    3. Topaz 2x Enhance each best photo:

    TOPAZ_API_KEY=$(security find-generic-password -s "topaz-api-key" -w)

    curl --request POST \ --url https://api.topazlabs.com/image/v1/enhance \ --header "X-API-Key: ${TOPAZ_API_KEY}" \ --header 'accept: image/jpeg' \ --header 'content-type: multipart/form-data' \ --form 'model=Low Resolution V2' \ --form 'output_scale_factor=2' \ --form 'output_format=jpeg' \ --form "image=@/tmp/ig-reddit-quote/${slug}-best.jpg" \ --output "/tmp/ig-reddit-quote/${slug}-enhanced.jpg"

    If sync returns JSON with process_id instead of image bytes, use async flow:

    # Submit async
    RESPONSE=$(curl -s --request POST \
      --url https://api.topazlabs.com/image/v1/enhance/async \
      --header "X-API-Key: ${TOPAZ_API_KEY}" \
      --header 'content-type: multipart/form-data' \
      --form 'model=Low Resolution V2' \
      --form 'output_scale_factor=2' \
      --form 'output_format=jpeg' \
      --form "image=@/tmp/ig-reddit-quote/${slug}-best.jpg")

    PROCESS_ID=$(echo "$RESPONSE" | jq -r '.process_id')

    Poll until Completed

    while true; do STATUS=$(curl -s --header "X-API-Key: ${TOPAZ_API_KEY}" \ "https://api.topazlabs.com/image/v1/status/${PROCESS_ID}" | jq -r '.status') [ "$STATUS" = "Completed" ] && break sleep 3 done

    Download

    curl -s --header "X-API-Key: ${TOPAZ_API_KEY}" \ "https://api.topazlabs.com/image/v1/download/${PROCESS_ID}" \ --output "/tmp/ig-reddit-quote/${slug}-enhanced.jpg"

    4. Write manifest to /tmp/ig-reddit-quote/manifest.json:

    {
      "destination": "Barcelona",
      "category": "Cheap Eats",
      "reddit_post_count": 150,
      "cover_photo": "/tmp/ig-reddit-quote/cover-enhanced.jpg",
      "slides": [
        {
          "name": "Bar CaΓ±ete",
          "quote": "Went here on a random Tuesday and had the best patatas bravas of my life.",
          "subreddit": "r/barcelona",
          "photo": "/tmp/ig-reddit-quote/bar-canete-enhanced.jpg",
          "original": "/tmp/ig-reddit-quote/bar-canete-best.jpg",
          "source_url": "instagram.com/p/XXX/",
          "topaz_enhanced": true
        }
      ]
    }
    

    Sub-agent 2: Text Overlays

    Read manifest. Create overlays using instagram-photo-text-overlay skill on enhanced images.

    Slide 1 (Cover) β€” clean style:

    python3 /Users/psy/.openclaw/workspace/skills/instagram-photo-text-overlay/scripts/overlay.py \
      --input /tmp/ig-reddit-quote/cover-enhanced.jpg \
      --output /tmp/ig-reddit-quote/slide-1.jpg \
      --title "Top {COUNT} {CATEGORY} in {DESTINATION}" \
      --subtitle "Insider Takes from Reddit ({N}+ posts)" \
      --style clean --watermark "tabiji.ai"
    

    Slides 2+ β€” quote style, one per attraction:

    python3 /Users/psy/.openclaw/workspace/skills/instagram-photo-text-overlay/scripts/overlay.py \
      --input /tmp/ig-reddit-quote/{slug}-enhanced.jpg \
      --output /tmp/ig-reddit-quote/slide-{N}.jpg \
      --title "{ATTRACTION_NAME}" \
      --quote "{REDDIT_QUOTE}" \
      --author "{SUBREDDIT}" \
      --style quote --watermark "tabiji.ai"
    

    Output: slides at /tmp/ig-reddit-quote/slide-{1-N}.jpg

    Sub-agent 3: Publish to Instagram

    1. Host images in tabiji repo (img/instagram/), git push, use raw GitHub URLs 2. Create carousel item containers 3. Create carousel container with caption 4. Publish 5. Get permalink 6. Cleanup hosted images + local temp files

    Instagram API Auth

    Keys from macOS Keychain:

  • instagram-access-token β€” Graph API token
  • instagram-account-id β€” IG user ID (17841449394591017)
  • Topaz API Auth

  • topaz-api-key β€” Topaz Labs API key (macOS Keychain)
  • Caption Template

    {flag_emoji} Top {COUNT} {CATEGORY} in {DESTINATION}

    Real recommendations from {N}+ Reddit posts 🧡

    πŸ“ Swipe for the spots + what Redditors actually said: 1. {Attraction 1} 2. {Attraction 2} ...

    Full list with maps, prices & more Reddit recs πŸ‘‰ {POPULAR_PICKS_URL}

    πŸ’¬ {PROVOCATIVE_QUESTION β€” e.g. "What's the most overrated restaurant you've been to abroad?" or "Would you trust a stranger's Reddit rec over a Michelin star?"}

    #{destination} #{category_tag} #redditfinds #traveltips #foodietravel #localfavorites #tabiji

    Tips

  • Pick quotes that are specific and personal β€” "best patatas bravas of my life" beats "this place is great"
  • Keep quotes under ~120 chars so they render well on the slide
  • If a quote is too long, trim it but keep the vivid part
  • The cover title should feel like a listicle: "Top 7 Cheap Eats in Barcelona"
  • Topaz model: Low Resolution V2 β€” designed for web-sourced images (our exact use case)
  • Topaz rate limits: If HTTP 429, use exponential backoff. Sequential processing of 6-8 images should be fine.
  • Keep originals in manifest so you can fall back if Topaz fails on a specific image
  • πŸ“‹ Tips & Best Practices

  • Pick quotes that are specific and personal β€” "best patatas bravas of my life" beats "this place is great"
  • Keep quotes under ~120 chars so they render well on the slide
  • If a quote is too long, trim it but keep the vivid part
  • The cover title should feel like a listicle: "Top 7 Cheap Eats in Barcelona"
  • Topaz model: Low Resolution V2 β€” designed for web-sourced images (our exact use case)
  • Topaz rate limits: If HTTP 429, use exponential backoff. Sequential processing of 6-8 images should be fine.
  • Keep originals in manifest so you can fall back if Topaz fails on a specific image