Pixelvault email images
Host the local images referenced by an email template on PixelVault and rewrite them to permanent CDN URLs. Use when the user is building or sending an email (Resend, react-email, Nodemailer, Postmark, SendGrid) that references local image files, or says "my email images are broken", "images don't show in Gmail/Outlook", "host the images in this email", "prepare this email template for sending". Gmail doesn't render base64 `data:` images (and many Outlook clients don't either), so every image needs a public URL — this skill finds the local refs, uploads them, and swaps in the hosted URLs.From its SKILL.md
npx -y skills add pixelvault-dev/skill --skill pixelvault-email-imagesAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
6.6 KB, ~1.5k tokens by cl100k_base, as published. Nobody here has run it
PixelVault Email Images
Take an email template that references local images and make it send-ready: upload each local image to PixelVault and rewrite the reference to the permanent CDN URL it returns.
Why this is needed
An email can only reliably render an image that lives at a public URL:
- Base64
data:images don't render in Gmail, and inconsistently in Outlook — recipients see a broken box. - CID attachments bloat every send and hurt deliverability.
- A hosted
https://URL renders everywhere. That's the target.
Resend (and every other email API) sends the message but doesn't host images, so the images have to live somewhere public first. PixelVault URLs are permanent and immutable on zero-egress storage — they render for the life of the inbox and cost the same whether the email is opened once or a million times.
Prerequisites
The pixelvault CLI must be installed and configured. If the command is not
found, install it:
npm install -g pixelvault-cli
If no API key is configured, tell the user to run /pixelvault-setup first or set
PIXELVAULT_API_KEY in their environment.
Steps
-
Check CLI + auth — Run
which pixelvault, thenpixelvault whoami --json. If either fails, stop and tell the user to run/pixelvault-setupor setPIXELVAULT_API_KEY. -
Find image references in the template(s) at
$ARGUMENTS. Look for:- HTML:
<img src="..."> - react-email / JSX:
<Img src="..." />— only whensrcis a string literal (src="./logo.png"orsrc={"./logo.png"}) - CSS/inline:
url(...)instyle/background - Inline base64
data:image/...URIs
Classify each reference and handle only the ones you can safely resolve:
- Local file path (relative or absolute path that exists on disk) → host it. Resolve relative paths against the template file's directory.
- Inline base64
data:URI → host it via the decode step below. - Non-literal
src={expr}— a variable, prop, or expression such assrc={logo}orsrc={props.image}→ do NOT rewrite it. There's no literal path to resolve, and editing it would corrupt the template. Report it instead so the user can host that asset and pass the URL in themselves. - Already
http(s)://, acid:reference, or a 1×1 tracking pixel → skip.
- HTML:
-
Deduplicate — the same asset (a logo) is often referenced many times. Upload each unique file once and reuse the URL.
-
Upload each unique image:
# Local file on disk pixelvault upload <resolved-path> # → https://img.pixelvault.dev/proj_abc/img_xyz.pngFor an inline base64
data:URI, decode the payload to a temp file first, then upload that file (pick the extension from the URI's mime type):# data:image/png;base64,AAAA... → temp file → upload printf '%s' "<base64-payload>" | base64 -d > /tmp/pv-email-1.png pixelvault upload /tmp/pv-email-1.pngThe CLI prints one CDN URL per line to stdout.
-
Rewrite the references you hosted, replacing each local path or base64
data:URI with its hosted URL. Leave the non-literalsrc={expr}references untouched — you only reported those. When the image has a known displaywidth, append?w=<2×width>&fmt=autofor retina and keep thewidthattribute — e.g.width="120"becomessrc="https://img.pixelvault.dev/…?w=240&fmt=auto". -
Report the mapping (source → hosted URL), which files you edited, and any non-literal
src={expr}references you left for the user to handle.
Output Contract
pixelvault uploadprints only URLs to stdout (one per line); human messages go to stderr. Use--jsonif you need the id/size/filename.- Edit the template files in place and summarize every change — never rewrite a reference silently.
Error Handling
| Error | Action |
|---|---|
command not found: pixelvault | Tell user to npm install -g pixelvault-cli |
No API key configured | Tell user to run /pixelvault-setup or set PIXELVAULT_API_KEY |
401 Unauthorized | API key invalid — tell user to run pixelvault login |
413 Payload Too Large | Image exceeds plan limit (5 MB free, 50 MB paid) |
415 Unsupported Media Type | File is not a supported image format |
| Local path not found | Report which reference couldn't be resolved; don't rewrite it |
Example
Given emails/receipt.tsx:
import { Img } from "@react-email/components";
export function Receipt() {
return <Img src="./assets/logo.png" width="120" alt="Acme" />;
}
After running the skill:
import { Img } from "@react-email/components";
export function Receipt() {
return <Img src="https://img.pixelvault.dev/proj_abc/img_xyz.png?w=240&fmt=auto" width="120" alt="Acme" />;
}
Now the template is safe to render and hand to Resend:
import { Resend } from "resend";
import { render } from "@react-email/render";
import { Receipt } from "./emails/receipt";
const resend = new Resend(process.env.RESEND_API_KEY);
await resend.emails.send({
from: "[email protected]",
to: "[email protected]",
subject: "Your receipt",
html: await render(<Receipt />),
});
Note on deliverability
Hosting images well makes them render reliably and keeps egress flat — it does not affect inbox placement. Deliverability is a function of the sending domain and SPF/DKIM/DMARC — the email provider gives you the authentication tooling, but the DNS records and list hygiene are yours. Don't promise better open rates; promise images that don't break.
Related
/pixelvault-upload— host individual images without the template rewrite./pixelvault-transform— the full transform vocabulary for the hosted URLs (?w=,?fmt=,?segment=, watermarks).
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.