{"id":"4395c99f-7409-46e3-a926-868133350863","slug":"linkedin-gif-post-skill","kind":"skill","name":"linkedin-gif-post-skill","summary":"Claude Code skill: turn a resource into a LinkedIn post with an animated GIF in your brand and a caption that sells the click","owner":"josueh04","repoUrl":"https://github.com/josueh04/linkedin-gif-post-skill","license":"MIT","licenseTier":"permissive","trust":"community","stars":0,"match":null,"fewStars":true,"format":"skill","createdAt":"2026-10-08T02:28:33.000Z","addedAt":"2026-10-21T10:30:54.611Z","logoUrl":"https://avatars.githubusercontent.com/u/36378702?u=f6239426a745ae22208ce999c69cb1f754fe17fd&v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["developer-tools"],"tags":["claude-code","content-marketing","gif","hyperframes","linkedin"],"runtime":"binary","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-22T16:41:04.443Z","sample":false,"url":"https://conduits.dev/tools/linkedin-gif-post-skill","language":"Python","transports":["stdio"],"install":{},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"<h1 align=\"center\">LinkedIn GIF Post</h1>\n\n<p align=\"center\"><strong>Turn the resource you want to share into a LinkedIn post people stop for: a looping GIF in your brand and a caption that sells the click.</strong></p>\n\n<p align=\"center\">\n  <img src=\"https://img.shields.io/badge/status-alpha-orange\" alt=\"status: alpha\">\n  <a href=\"LICENSE\"><img src=\"https://img.shields.io/badge/license-MIT-blue\" alt=\"license: MIT\"></a>\n  <img src=\"https://img.shields.io/badge/Claude%20Code-skill-d97757\" alt=\"Claude Code skill\">\n  <img src=\"https://img.shields.io/badge/node-%3E%3D22-brightgreen\" alt=\"node >= 22\">\n  <img src=\"https://img.shields.io/badge/python-%3E%3D3.9-3776AB\" alt=\"python >= 3.9\">\n  <a href=\"https://github.com/heygen-com/hyperframes\"><img src=\"https://img.shields.io/badge/built%20on-HyperFrames-6366F1\" alt=\"built on HyperFrames\"></a>\n</p>\n\n<table>\n  <tr>\n    <td align=\"center\"><img src=\"assets/gallery/radar.gif\" width=\"260\" alt=\"Radar: buyer pains found, then fed into the model\"><br><sub><b>Radar</b> · a scan finds the pains, the model turns them into formats</sub></td>\n    <td align=\"center\"><img src=\"assets/gallery/star-bento.gif\" width=\"260\" alt=\"Star bento: five cards, each with its own chart\"><br><sub><b>Star bento</b> · five live cards, nothing ever clears</sub></td>\n    <td align=\"center\"><img src=\"assets/gallery/core.gif\" width=\"260\" alt=\"Core: sources stream into a core and land on a 3D calendar\"><br><sub><b>Core</b> · sources in, a month of posts out on a 3D calendar</sub></td>\n  </tr>\n  <tr>\n    <td align=\"center\"><img src=\"assets/gallery/constellation.gif\" width=\"260\" alt=\"Constellation: one input becomes five outputs\"><br><sub><b>Constellation</b> · one input, five outputs, a camera push</sub></td>\n    <td align=\"center\"><img src=\"assets/gallery/light-bento.gif\" width=\"260\" alt=\"Light bento: app-style cards on a light canvas\"><br><sub><b>Light bento</b> · app-style cards on a light canvas</sub></td>\n    <td align=\"center\"><img src=\"assets/gallery/stack-3d.gif\" width=\"260\" alt=\"Stack: layers explode up in 3D\"><br><sub><b>Stack</b> · an interview, then layers that explode up in 3D</sub></td>\n  </tr>\n</table>\n\n<p align=\"center\"><sub>Graphics made with this method for real LinkedIn posts. The full GIFs are 1080x1350; these previews are scaled down.</sub></p>\n\nA Claude Code skill for anyone who shares research, checklists, guides or playbooks on LinkedIn and gets little back. It reads the resource and your website, then designs an animated graphic for that resource: its own concept, layout and motion, previewing what the resource contains in your colors and fonts. It is not a template with your words swapped in. It renders the graphic locally with [HyperFrames](https://github.com/heygen-com/hyperframes), checks it against LinkedIn's limits, and rewrites the caption so the first two lines say what the reader gets.\n\nIt comes out of a real production: a frame-by-frame study of eight high-performing lead-magnet posts and 192 posts by their authors, then a week of posts made, measured and remade. Every rule in it exists because a version without it did worse.\n\n> [!IMPORTANT]\n> **Alpha.** The skill and the scripts work end to end on macOS, and the gates pass on every graphic above. Each graphic is composed for its resource from a blank frame, with the method in [`compose.md`](skills/linkedin-gif-post/references/compose.md). Two templates ship as worked examples: `blank` and `research_bento`. The [Roadmap](#roadmap) says what is next.\n\n## Installation\n\n### 1. Get the skill\n\n```bash\ngit clone https://github.com/josueh04/linkedin-gif-post-skill.git\ncp -R linkedin-gif-post-skill/skills/linkedin-gif-post ~/.claude/skills/\npip install pillow numpy\n```\n\nTo keep the skill inside one project, copy it into that project's `.claude/skills/` instead.\n\n<details>\n<summary><strong>What you need</strong></summary>\n\n| Need | Detail |\n|---|---|\n| macOS | Linux should work (untested) |\n| Claude Code | Any version with skills |\n| Node.js | 22 or newer (HyperFrames requires it) |\n| Python | 3.9 or newer, with Pillow and numpy |\n| ffmpeg | `brew install ffmpeg` on macOS |\n| Google Chrome | HyperFrames renders through it |\n\n</details>\n\n### 2. Ask for a post\n\nIn Claude Code:\n\n```\nMake a LinkedIn GIF post for this research: https://your-site.com/research/your-piece\nOur site is https://your-site.com\n```\n\nThe skill:\n- reads the resource;\n- extracts your brand into `brand.json` and shows it to you;\n- builds the animation and shows you a contact sheet before it renders;\n- renders and gates the GIF;\n- writes the caption.\n\nYou get `graphic.gif`, `graphic-frame.png` and `caption.md` in `posts/<slug>/`.\n\n### 3. Or run it by hand\n\n```bash\ncd ~/.claude/skills/linkedin-gif-post\npython3 scripts/brand_extract.py https://your-site.com --out posts/my-post\npython3 scripts/new_animation.py --out posts/my-post --brand posts/my-post/brand.json\n# edit posts/my-post/animation/index.html: header, cards, CTA\npython3 scripts/snapshot_sheet.py posts/my-post/animation\npython3 scripts/render_gif.py posts/my-post/animation\npython3 scripts/gif_gate.py posts/my-post/graphic.gif\n```\n\n## Why This Skill Exists\n\n### #1: The Image Repeats the Caption\n\n**The Problem.** Most resource posts use a static text card or a stock photo, which gives the scroll no reason to stop and the reader no preview of the resource.\n\n**The Fix.** The GIF shows the resource itself as a working system. A method appears as a line of stations, the checklist is scanned row by row, and the data is called out pair by pair. The cards are dense on purpose: dense enough to read as a lot of value, too detailed to absorb in the feed.\n\n### #2: The First Two Lines Waste the Preview\n\n**The Problem.** LinkedIn shows about 210 characters before \"...see more\". Captions spend them on context, a quote chain or a thesis, and the offer shows up in paragraph three.\n\n**The Fix.** [`copy.md`](skills/linkedin-gif-post/references/copy.md) puts the reader's stake in line 1, one number per line with its meaning, and a numbered list that mirrors the GIF's cards. Lead-magnet captions with a numbered list drew 1.53x their author's usual comments.\n\n### #3: Animation That Looks Cheap or Breaks LinkedIn's Limits\n\n**The Problem.** A screen recording turned into a GIF can be 10 MB and over LinkedIn's 250-frame limit. It can open on a blank frame and cut visibly at the loop.\n\n**The Fix.** Compositions are HTML with a GSAP timeline, rendered deterministically. [`gif_gate.py`](skills/linkedin-gif-post/scripts/gif_gate.py) blocks a GIF unless it passes all eight gates: frames, bytes, size, the loop flag, fps, a seamless loop, enough motion, and a solid CTA band. When a GIF runs heavy, [`weight_map.py`](skills/linkedin-gif-post/scripts/weight_map.py) shows which area costs the bytes.\n\n### #4: Off-Brand Graphics\n\n**The Problem.** Templates come in someone else's colors and fonts, and a near-copy of a competitor's post reads as a copy.\n\n**The Fix.** [`brand_extract.py`](skills/linkedin-gif-post/scripts/brand_extract.py) reads your site's CSS variables, palette, fonts and wordmark, and downloads the fonts (OFL) so renders stay local. Every color and font in the template is a token. [`analyze_reference.py`](skills/linkedin-gif-post/scripts/analyze_reference.py) measures a post you admire, so you can borrow the principle, not the layout.\n\n### #5: Every Post Looks the Same\n\n**The Problem.** A template tool gives every post the same layout with new words, and after the second post the feed sees the same picture again.\n\n**The Fix.** [`compose.md`](skills/linkedin-gif-post/references/compose.md) is the method for designing from scratch:\n- name the resource's shape (a process, a checklist, a transformation, a comparison...);\n- write a one-sentence concept;\n- sketch the zones;\n- plan the beats with a library of seek-safe motion patterns;\n- build on a `blank` frame that carries only the brand, the header and the CTA.\n\nWhen a composition works, `save_template.py` keeps it for the next resource of the same shape.\n\n## What's Inside\n\n- **[SKILL.md](skills/linkedin-gif-post/SKILL.md)**: the workflow, from reading the resource to checking the live post, and the rules with their reasons.\n- **Scripts**\n  - [`brand_extract.py`](skills/linkedin-gif-post/scripts/brand_extract.py): colors, fonts and logo from a website, into `brand.json`.\n  - [`new_animation.py`](skills/linkedin-gif-post/scripts/new_animation.py): copies a template into a post folder and applies the brand tokens.\n  - [`snapshot_sheet.py`](skills/linkedin-gif-post/scripts/snapshot_sheet.py): ten moments of the loop on one sheet, to review before rendering.\n  - [`render_gif.py`](skills/linkedin-gif-post/scripts/render_gif.py): renders with HyperFrames and encodes the GIF. If the file is too heavy, it steps down colors, dithering, fps and width.\n  - [`gif_gate.py`](skills/linkedin-gif-post/scripts/gif_gate.py): the eight release gates.\n  - [`weight_map.py`](skills/linkedin-gif-post/scripts/weight_map.py): where a GIF spends its bytes.\n  - [`analyze_reference.py`](skills/linkedin-gif-post/scripts/analyze_reference.py): stats, a frame sheet and a motion heat map of any public LinkedIn post.\n  - [`save_template.py`](skills/linkedin-gif-post/scripts/save_template.py): keeps a composition that worked as a template, with a README to fill in.\n- **Templates**:\n  - [`blank`](skills/linkedin-gif-post/assets/templates/blank/index.html): the frame only (brand tokens, header slots, the CTA band, an empty timeline), and the starting point for every original composition.\n  - [`research_bento`](skills/linkedin-gif-post/assets/templates/research_bento/README.md): a worked example for a checklist-plus-data research post.\n- **References**: [compose](skills/linkedin-gif-post/references/compose.md) (read it first), [design](skills/linkedin-gif-post/references/design.md), [copy](skills/linkedin-gif-post/references/copy.md), [HyperFrames notes](skills/linkedin-gif-post/references/hyperframes.md), [evidence](skills/linkedin-gif-post/references/evidence.md).\n\n## What You Need to Provide\n\n| Input | Required? | How |\n|---|---|---|\n| The resource | Yes | A URL or a file: the research, checklist, guide or playbook the post shares |\n| Your website | Recommended | A URL; the brand is read from its CSS. Without it, you edit the tokens by hand |\n| A logo file | Optional | An SVG or PNG. Without it, the template uses your wordmark as text |\n| A post you admire | Optional | A LinkedIn URL for `analyze_reference.py` |\n\n> [!NOTE]\n> Everything renders on your machine. The scripts turn off HyperFrames' anonymous telemetry (`DO_NOT_TRACK=1`) and unset `GEMINI_API_KEY`, so no frames leave the machine. `brand_extract.py` fetches only the site you give it and the Fontsource CDN. Claude reads the resource you share, so it is sent to the model as context.\n\n## Roadmap\n\n| Phase | What | Status |\n|---|---|---|\n| 1. Core | The skill, the scripts, brand extraction, caption rules and the gates | Done on macOS |\n| 2. Compose from scratch | `compose.md`, the `blank` frame, the motion library and `save_template.py` | Done. Tested with a fresh agent on a new resource |\n| 3. More worked examples | Radar, core, constellation and stack as brand-token templates, like the gallery | Next |\n| 4. Pilot | Someone outside the project, with their own brand and resource | Next |\n| 5. Distribution | A Claude Code plugin and `npx skills add` | Later |\n\n## License\n\n[MIT](LICENSE). The bundled fonts are under the SIL Open Font License 1.1 ([licenses](skills/linkedin-gif-post/assets/templates/research_bento/fonts/licenses/)). It is built on [HyperFrames](https://github.com/heygen-com/hyperframes) by HeyGen (Apache-2.0) and GSAP, which run at render time and are not bundled. The logos in the gallery belong to their owners and appear only as examples of output.\n"}