OpenClaw · Skill
Itinerary Carousel Post
End-to-end pipeline: itinerary URL → photo sourcing → text overlays → Instagram carousel publish.
Install
Start with the primary install command. Alternate entrypoints are included below for ClawHub and OpenClaw CLI users.
Primary command
clawhub install psyduckler/itinerary-carousel-postClawHub installer
npx clawhub@latest install psyduckler/itinerary-carousel-postOpenClaw CLI
openclaw skills install psyduckler/itinerary-carousel-postDirect OpenClaw install
openclaw install psyduckler/itinerary-carousel-postWhat this skill does
End-to-end pipeline: itinerary URL → photo sourcing → text overlays → Instagram carousel publish.
Why it matters
Handles the full pipeline from URL to published post in one command, replacing separate photo research, image editing, and manual Instagram upload steps.
Typical use cases
- Turning a tabiji.ai city itinerary into a ready-to-post Instagram carousel
- Sourcing and scoring destination photos without manual searching
- Adding attraction names and insider tips as text overlays to travel photos
- Publishing multi-slide Instagram posts programmatically from a single URL
- Automating social content creation for each new tabiji.ai itinerary
Source instructions
Create Instagram Carousel Post
End-to-end pipeline: itinerary URL → photo sourcing → text overlays → Instagram carousel publish.
Parameters
- itinerary_url (required): tabiji.ai itinerary URL (e.g.
https://tabiji.ai/i/thaw-dome/) - destination (required): City/region name (e.g. "Kuala Lumpur")
- attractions (required): List of 5 attraction names + short descriptions
- caption (optional): Custom caption. If omitted, generate one with destination name, attraction list, CTA to link in bio, and relevant hashtags.
Pipeline (3 chained sub-agents recommended)
Split into 3 sub-agents for reliability. Each writes outputs to /tmp/ig-carousel/.
Sub-agent 1: Photo Finding
Use the instagram-photo-find skill workflow for each subject (1 destination + 5 attractions = 6 total).
For each subject:
web_search:site:instagram.com/p/ "{subject}" photo(10 results)- Download top 5 candidates:
curl -s -L -o /tmp/ig-carousel/raw-{slug}-{n}.jpg "https://www.instagram.com/p/{shortcode}/media/?size=l" - Vision-score each with: "Rate 1-10 as hero destination photo for {subject}. Description + score only."
- Keep best per subject →
/tmp/ig-carousel/{slug}-best.jpg
Output: 6 best images + JSON manifest at /tmp/ig-carousel/manifest.json:
[{"slug": "kuala-lumpur", "subject": "Kuala Lumpur", "score": 7, "path": "/tmp/ig-carousel/kuala-lumpur-best.jpg", "source": "instagram.com/p/XXX/"}]
Sub-agent 2: Text Overlays
Read manifest from sub-agent 1. Run overlay script for each image.
Slide 1 (cover) — clean style:
python3 skills/instagram-photo-text-overlay/scripts/overlay.py \
--input /tmp/ig-carousel/{dest-slug}-best.jpg \
--output /tmp/ig-carousel/slide-1.jpg \
--title "{N} Day {DESTINATION} Itinerary Highlights" \
--style clean --watermark "tabiji.ai"
Slides 2–6 — quote style per attraction with insider tip:
python3 skills/instagram-photo-text-overlay/scripts/overlay.py \
--input /tmp/ig-carousel/{slug}-best.jpg \
--output /tmp/ig-carousel/slide-{N}.jpg \
--title "{ATTRACTION}" \
--quote "{Specific insider tip about THIS attraction — must directly reference the place in the title, not a generic travel tip}" \
--author "tabiji.ai" \
--style quote --watermark "tabiji.ai"
Output: 6 overlay images at /tmp/ig-carousel/slide-{1-6}.jpg
Sub-agent 3: Publish to Instagram
-
Host images publicly — copy slides to tabiji repo (
img/instagram/), git push, use raw GitHub URLs (https://raw.githubusercontent.com/psyduckler/tabiji/main/img/instagram/slide-{N}.jpg). Wait ~30s after push for GitHub CDN. -
Create carousel item containers (one per slide):
curl -s -X POST "https://graph.facebook.com/v21.0/${IG_USER}/media" \
-d "image_url=${PUBLIC_URL}" \
-d "is_carousel_item=true" \
-d "access_token=${IG_TOKEN}"
- Create carousel container with all children + caption:
curl -s -X POST "https://graph.facebook.com/v21.0/${IG_USER}/media" \
--data-urlencode "caption=${CAPTION}" \
-d "media_type=CAROUSEL" \
-d "children=${CHILD_IDS}" \
-d "access_token=${IG_TOKEN}"
- Publish:
curl -s -X POST "https://graph.facebook.com/v21.0/${IG_USER}/media_publish" \
-d "creation_id=${CAROUSEL_ID}" \
-d "access_token=${IG_TOKEN}"
- Get permalink (or verify publish on rate-limit error):
If media_publish returns a POST_ID, get the permalink directly:
curl -s "https://graph.facebook.com/v21.0/${POST_ID}?fields=permalink&access_token=${IG_TOKEN}"
If media_publish returns error 2207051 (rate limit / action blocked): Instagram sometimes processes the request despite returning an error. Always verify by checking the account's recent media before declaring failure:
curl -s "https://graph.facebook.com/v21.0/${IG_USER}/media?fields=id,timestamp,permalink&limit=1&access_token=${IG_TOKEN}"
If the most recent post timestamp is within the last few minutes, the publish likely succeeded — grab that permalink.
- Cleanup hosted images — after publish is confirmed, delete the images from the tabiji repo and push:
cd /path/to/tabiji/repo
git rm img/instagram/slide-*.jpg
git commit -m "cleanup: remove instagram carousel images after publish"
git push
Also clean up local temp files:
rm -rf /tmp/ig-carousel/
Output: Instagram post URL
Instagram API Auth
Keys from macOS Keychain:
instagram-access-token— Graph API tokeninstagram-account-id— IG user ID (17841449394591017)
Caption Template
🇲🇾 {N} Nights in {Destination} — {Itinerary Subtitle}
{One-line hook about the trip}
📍 Swipe through our top 5 picks:
1. {Attraction 1} — {one-line reason}
2. {Attraction 2} — {one-line reason}
3. {Attraction 3} — {one-line reason}
4. {Attraction 4} — {one-line reason}
5. {Attraction 5} — {one-line reason}
Full free itinerary with tips, prices & Reddit recs 👉 {ITINERARY_URL}
💬 {PROVOCATIVE_QUESTION — e.g. "Is 5 nights enough for {Destination} or do you need more?" or "What's the one thing most tourists get wrong about {Destination}?"}
#{destination_hashtag} #{country} #travelitinerary #foodietravel #southeastasia #asiatravel #travelguide #tabiji
Tips
- Raw GitHub URLs work for IG image_url; tabiji.ai Cloudflare CDN may trigger format validation errors.
- Add
sleep 1between container creation calls to avoid rate limits. - If a subject yields low photo scores (<5), broaden search: try Unsplash/Flickr or more specific landmark names.
- Islamic/cultural museums tend to have fewer quality IG photos — try searching the museum's official IG handle.