Skip to main content
ClaudeWave
Skill1.2k repo starsupdated 5d ago

create-imessage-mockup

Render pixel-accurate iMessage screenshot mockups (DM or group) from a thread JSON. Supports minimal, with-keyboard, and full iPhone 15 Pro frame variants. Outputs HTML + PNG.

Install in Claude Code
Copy
git clone --depth 1 https://github.com/gooseworks-ai/goose-skills /tmp/create-imessage-mockup && cp -r /tmp/create-imessage-mockup/skills/ads/packs/video-ad-formats/create-imessage-mockup ~/.claude/skills/create-imessage-mockup
Then start a new Claude Code session; the skill loads automatically.

SKILL.md

# create-imessage-mockup

Generate iMessage screenshots that look like real iOS captures — correct bubbles with tails, typing indicators, timestamps, "Delivered" captions, group avatars + sender names, keyboard chrome, and an optional iPhone 15 Pro bezel with Dynamic Island and status bar.

## Purpose

Turn a structured thread JSON into a believable iMessage screenshot — first as standalone HTML (`generate.js` + `templates/chat.css`), then rasterized to PNG with headless Chromium (`screenshot.js`/`render.js` via Playwright). It is the atom you reach for when an ad, social post, or video scene needs a fake-but-convincing iOS message capture.

What it gets right, grounded in the renderer:

- **Bubble runs and tails** — blue `sent` bubbles (right) and gray `received` bubbles (left), with a curved tear-drop tail drawn only on the *last* bubble of each consecutive sender run (`isLastOfRun` in `generate.js`).
- **Dark-themed iOS chrome** — `theme: "dark"` flips the page to the iOS dark conversation look; the status bar, Dynamic Island, and keyboard match iPhone 15 Pro.
- **Group affordances** — group threads (`mode: "group"`) add per-sender colored avatar circles, sender names above the first bubble of a run, and a 4-tile group-header badge.
- **Beats for storyboards** — `timestamp` pills, a static-but-mid-animation `typing` three-dot bubble, `attachment` cards, and "Delivered"/"Read" captions let you stage individual frames of a conversation.
- **Three crops** — `--minimal` (bubbles only), `--with-keyboard` (header + iOS keyboard), and `--with-iphone-frame` (full bezel + Dynamic Island + status bar over a gradient backdrop).

The atom embeds **no LLM** — it is deterministic. The orchestrating agent is responsible for composing the thread JSON; the renderer only draws exactly what the JSON says.

## When to use

- Need a fake iMessage screenshot for an ad, social post, video scene, or product mockup.
- Want a side-by-side hero image showing a conversation in an iPhone frame.
- Need a typing indicator or "Delivered" beat for a video storyboard.

If you're rendering programmatic graphic frames more broadly (cards, posters, infographics), use `create-goose-graphics` instead.

## Inputs

The skill is deterministic — it does not embed an LLM. To translate a free-form prompt into a thread, the orchestrating agent (you) composes a JSON file matching the schema below, then invokes the renderer.

### Thread JSON schema

```json
{
  "mode": "dm" | "group",
  "title": "Karaoke Crew",
  "participants": [
    { "id": "me",    "name": "Me",    "self": true },
    { "id": "sarah", "name": "Sarah", "color": "#FF9500", "initials": "S" }
  ],
  "messages": [
    { "type": "timestamp", "label": "iMessage\nToday 9:41 AM" },
    { "type": "timestamp", "bold": "Sat, Jan 2", "light": "11:07" },
    { "type": "text",      "from": "sarah", "text": "Did we crash it?" },
    { "type": "text",      "from": "me",    "text": "Couldn't withstand our friendship", "delivered": true, "read": false },
    { "type": "typing",    "from": "sarah" }
  ],
  "keyboard": { "leftIcon": "plus" }
}
```

- `mode` — `dm` or `group`. If omitted, auto-detected from the participant count.
- `participants[].self: true` marks the user (sent bubbles, no avatar).
- `participants[].color` is the avatar background; defaults from a 6-color palette.
- `participants[].initials` defaults to the first letter of `name`.
- `messages[]`:
  - `timestamp` — centered pill. Use `label` (newline-separated bold/light) or explicit `bold` and `light` fields.
  - `text` — text bubble. `delivered: true` on the last sent bubble in a run renders the "Delivered" caption (or "Read" if `read: true`).
  - `typing` — animated three-dot bubble (rendered as a static mid-animation frame for screenshot determinism).
- `keyboard.leftIcon` — `"plus"` (default) or `"camera"`.

## CLI

```bash
node render.js --thread examples/group-with-frame.json --with-iphone-frame
node render.js --thread examples/dm-with-keyboard.json --with-keyboard
node render.js --thread examples/dm-minimal.json       --minimal
node render.js --thread my-thread.json --with-keyboard --output ./my-exports/ --name nightout
```

### Flags

| Flag | Effect |
|---|---|
| `--thread <path>` | (required) JSON file matching the schema above |
| `--prompt "<brief>"` | prints the schema and exits — agent must compose a thread.json and re-invoke |
| `--minimal` | bubbles + timestamps only (no header, no keyboard, no frame) |
| `--with-keyboard` | bubbles + iOS keyboard chrome (default) |
| `--with-iphone-frame` | full iPhone 15 Pro bezel + Dynamic Island + status bar + soft gradient backdrop |
| `--dm` / `--group` | force chat mode (otherwise auto-detected from participants) |
| `--name <slug>` | override the output folder slug |
| `--output <dir>` | parent dir for the dated output folder; default `./imessage-mockup-exports/` |

Frame flags are mutually exclusive.

## Output

```
<output>/<YYYY-MM-DD>-<slug>/
  index.html       # full standalone HTML
  screenshot.png   # rendered PNG (DPR 3, "Retina")
  thread.json      # copy of the input for reproducibility
```

Default `<output>` is `./imessage-mockup-exports/` in the cwd.

## Workflow

1. Receive a prompt or existing thread JSON.
2. If only a prompt was given: compose a thread.json matching the schema, save it.
3. Run `node render.js --thread <path> [flag]`.
4. Open the resulting PNG to verify the layout. If something looks wrong (clipping, wrong tail side, missing avatar), edit the thread JSON or the relevant template under `templates/` and re-render.

## Setup (one-time)

```bash
cd skills/ads/capabilities/create-imessage-mockup
npm install
npx playwright install chromium
```

## Files

| File | Purpose |
|---|---|
| `render.js` | CLI entry — parses flags, generates HTML, takes screenshot, writes outputs |
| `generate.js` | Thread JSON → standalone HTML page |
| `screenshot.js` | HTML → PNG via Playwright (chromium headless) |
| `templates/chat.css` | All visual s