# Artifacts Skill

Managed Cloudflare home for AI-generated **self-contained HTML** pages.

Production: **https://myartifacts.dev** (usercontent: `https://uc.myartifacts.dev`).

This is **not** Claude’s native Artifact UI. URLs from this service are hosted by Artifacts (`npx myartifacts`).

## Install

```bash
export ARTIFACTS_API_URL=https://myartifacts.dev
npx myartifacts setup
# or from this repo:
npx myartifacts skill install all
```

This installs three skills that work together:

| Skill | Owns |
| --- | --- |
| `artifacts` (this one) | publish / edit / share / recover |
| `artifact-design` | how a page should look — the design method |
| `artifact-dataviz` | charts, dashboards, stat tiles — the chart method |

Fallback: copy the three folders into the agent’s skills path manually:

| Agent | Skills path |
| --- | --- |
| Claude Code | `~/.claude/skills/` |
| Codex | `~/.codex/skills/` |
| Cursor | `~/.cursor/skills-cursor/` or project `.agents/skills/` |

## Make it yours (user-owned files)

Two files are **yours to edit and never overwritten** by `skill install` / `setup`
once they exist:

- `artifact-design/style.md` — your standing palette, type, and tone
- `artifact-dataviz/references/palette.md` — your chart color parameters

Edit those to customize output; the method files (SKILL.md) stay product-owned and
get updates on reinstall.

## Before you write HTML — design first

**Always follow the `artifact-design` skill** when creating or restyling page
content, and the `artifact-dataviz` skill for any chart, dashboard, or stat tile.
Hard constraints that always apply:

1. One self-contained HTML file, max 16 MiB, no external network at render time.
2. Embed fonts as `@font-face` **data URIs** (CSP blocks font CDNs / `connect-src`).
3. Tokenized light + dark via `:root`, `@media (prefers-color-scheme: dark)`, and `:root[data-theme="…"]`.
4. Real content only; `prefers-reduced-motion`; visible `:focus-visible`.

## Temporary workspace — leave no files behind

Unless the user explicitly asks to keep the HTML source at a specific path,
create and publish from a unique temporary directory. Do not write generated
HTML, `artifacts.json`, screenshots, or other working files into the user's
repository, home directory, Desktop, or current working directory.

Use `${TMPDIR:-/tmp}` so macOS uses its private temporary area and other Unix
systems fall back to `/tmp`. Never use a predictable shared filename such as
`/tmp/page.html`.

```bash
ARTIFACT_WORKDIR="$(mktemp -d "${TMPDIR:-/tmp}/myartifacts.XXXXXX")"
ARTIFACT_HTML="$ARTIFACT_WORKDIR/page.html"

# Write the self-contained page to "$ARTIFACT_HTML", then publish from the
# temporary directory so the CLI's artifacts.json is temporary too.
(cd "$ARTIFACT_WORKDIR" && npx myartifacts publish "$ARTIFACT_HTML" --title "My page")

# After the publish result has been captured and verification is complete:
rm -rf "$ARTIFACT_WORKDIR"
```

Keep the returned artifact ID and URL in the conversation or requested output,
not in an unrequested local file. If publishing fails, inspect what is needed,
then remove the temporary directory before finishing. If the user requests a
durable source file, write only to that requested path and say what was kept.

## Auth ladder

1. Anonymous `publish` (gets a claim token in metadata)
2. Browser sign-in at https://myartifacts.dev/login (Google/GitHub via Clerk)
3. `ARTIFACTS_TOKEN` / `artifacts token create` for CI
4. Commit `artifacts.json` (ids + urls only — never tokens)

## Commands

```bash
export ARTIFACTS_API_URL=https://myartifacts.dev
npx myartifacts publish ./page.html
npx myartifacts edit art_… --replace 'exact old' --with 'new' --base v41
npx myartifacts share art_…
npx myartifacts versions art_…
npx myartifacts revert art_… v1
npx myartifacts login
npx myartifacts claim art_… --token CLAIM_TOKEN
```

Local proof without Cloudflare credentials is available only to repository maintainers.
The public npm package is intentionally client-only and does not ship the API server:

```bash
npm run artifacts:serve -- --port 8787
export ARTIFACTS_API_URL=http://127.0.0.1:8787
```

## HTML rules

- One self-contained HTML file, max 16 MiB
- No external network at render time (`connect-src` denied)
- Inline scripts/styles OK; keep anchors unique for later `str_replace`
- Prefer surgical edits over full-file replace after first publish

## Edit recovery (do not full re-upload)

See [references/recovery.md](./references/recovery.md).

| Error | Action |
| --- | --- |
| `409 version_conflict` | Read current version from error; refresh anchors; retry with new `If-Match` |
| `422 no_match` | Use returned contexts; pick a unique exact substring still present |
| `422 ambiguous_match` | Lengthen the anchor until unique |

## Working loop (beautiful artifact)

```text
1. Read artifact-design skill → write design plan
2. Create a unique ${TMPDIR:-/tmp}/myartifacts.* workspace
3. Build self-contained HTML there (embedded fonts, dual theme)
4. Publish while cwd is that workspace, so artifacts.json stays temporary
5. Open /a/{id} — check light/dark, motion, focus, no console network
6. Surgical artifacts edit … --base vN for copy/CSS tweaks
7. artifacts share when ready for a recipient
8. Remove the temporary workspace after verification
```

## Mental model

```text
artifact-design  → page craft   (style.md = your taste, user-owned)
artifact-dataviz → chart craft  (references/palette.md = your colors, user-owned)
Artifacts Skill  → publish / edit / share / recover
CLI → HTTP API → Durable Object head → R2 blob
```

MCP is optional and out of the default path.
