Are you the author? Sign in to claim
Open-source, self-hosted Claude Code Artifacts on Cloudflare — publish, password-protect, and auto-update shareable HTML
English | 简体中文
Open-source, self-hosted Claude Code Artifacts: let any coding agent publish self-contained HTML/Markdown pages to shareable URLs, protect them with passwords (zero-knowledge, client-side encryption), and keep them updated as the project they describe evolves. Runs entirely on Cloudflare (Workers + D1 + R2), fits in the free tier, no accounts anywhere.
Hosted or self-hosted. coda0.com is the official managed instance, run by the project — point your agent at it for zero-setup publishing. Or self-host the engine on your own Cloudflare account (see below); it's the same MIT-licensed code either way.
flowchart LR
you["you"] -- "share the app's interaction flows as a page" --> agent["your agent"]
agent -- "POST /api/artifacts" --> worker["your Worker"]
worker -- "https://<instance>/a/3fKx9mQp2Wvb" --> url["shareable URL"]
later["later: the flows change"] --> status["agent runs<br/>artifact.mjs status"]
status -- "stale" --> regen["regenerates page"]
regen -- "PUT (same id)" --> worker2["your Worker"]
worker2 -- "same URL, v2" --> url
npx skills add coda0HQ/open-artifacts -s using-open-artifacts # project scope (.claude/skills/)
npx skills add coda0HQ/open-artifacts -s using-open-artifacts -g # or user scope
Works with Claude Code and any agent supporting the Agent Skills standard. Then point it at an instance — the hosted one, or your own:
export OPEN_ARTIFACTS_URL=https://coda0.com # hosted; or your self-hosted URL
No instance yet? references/deployment.md (bundled with the skill) lists
three ways to get one: use the public shared instance with zero setup,
self-host on your own Cloudflare account, or share a team instance, with a
trust-model table for picking based on content sensitivity.
The bundled SKILL.md and references/design.md teach the agent the design
philosophy: an expert-designer workflow (understand, explore, plan, build,
verify), an explicit anti-AI-slop list, modern CSS power moves, and a
5-direction library (Editorial / Modern minimal / Human / Tech utility /
Brutalist) with ready-to-paste OKLch palettes and font stacks for when no
brand is specified. references/tokens.css is the shared token contract the
Recipe builder injects into every HTML artifact before its theme fragment.
Adapted from
open-design,
Claude's artifact-design skill,
impeccable by Paul Bakaus
(Apache-2.0, interaction-state and anti-pattern rules),
Emil Kowalski (easing, frequency, and duration rules), and
Apple WWDC 2018 Designing Fluid Interfaces (canvas gesture physics).
Retargeted to this project's strict no-external-requests CSP.
Ask your agent to "publish this as an artifact" — it runs the bundled CLI:
node skills/using-open-artifacts/scripts/artifact.mjs validate \
.artifacts/recipes/app-interactions.recipe.json
node skills/using-open-artifacts/scripts/artifact.mjs create \
.artifacts/recipes/app-interactions.recipe.json
Every artifact is generated from a versioned JSON Recipe plus ordered
fragments. The Recipe owns title, favicon, format, scope, watch globs, channel,
level, Canvas mode, locality, and encryption policy. create and update
compose and validate in memory, then send exactly one final publish request.
git clone https://github.com/coda0HQ/open-artifacts && cd open-artifacts
pnpm install
npx wrangler d1 create open-artifacts # put database_id into wrangler.jsonc
npx wrangler r2 bucket create open-artifacts-content
pnpm run deploy
The schema applies itself on first request — no migration step. To restrict who can create artifacts on your instance (updates are always restricted by per-artifact write tokens):
npx wrangler secret put CREATE_TOKEN # then set OPEN_ARTIFACTS_TOKEN client-side
Local development: pnpm dev (state persists in .wrangler/state).
| Concern | Design |
|---|---|
| Identity | No accounts. Artifact ids are 12-char crypto-random (unguessable, unlisted). Creation returns a one-time writeToken; only its SHA-256 is stored. |
| Deterministic sources | A strict Recipe plus ordered fragments generates every Artifact. The builder injects tokens and, for Canvas, the vendored runtime and controls. Manifest v2 records Recipe/input/output hashes; direct HTML/Markdown CLI publishing is rejected. |
| Channels | artifact.channel binds an artifact to a stable URL. The CLI keeps a per-channel token (ch_) in .artifacts/credentials.json; presenting it on a later create updates the bound artifact (new version, same link) instead of minting a new one. Only the channel hash is stored server-side. |
| Local mode | artifact.local: true places private sources under gitignored .artifacts/recipes.local/ and .artifacts/fragments.local/, with state in manifest.local.json. Shared Recipes/fragments live under .artifacts/recipes/ and .artifacts/fragments/ and may be committed. Encrypted Recipes are always private. |
| Storage | D1 for metadata/tokens/version index, R2 for content bodies (content/<id>/<version>). Both strongly consistent — updates are visible immediately. |
| Versions | Every publish is an immutable version with an optional label and its own title, description, favicon, format, and encryption state, so history reflects what each version actually looked like. ?v=N views history; PUT accepts baseVersion and returns 409 on conflicts (override with force). |
| Serving | The Worker wraps stored content in a skeleton (CSS reset, emoji favicon, viewport, light/dark theme with a data-theme toggle) and serves it with Content-Security-Policy: sandbox allow-scripts ...; default-src 'none' — artifact scripts run in an opaque origin and cannot make any external request. |
| Link previews | Every page emits OpenGraph + Twitter tags (title, description, image). GET /og/:id returns a 1200x630 PNG card rasterized on the edge with @resvg/resvg-wasm from an embedded Inter subset — a real raster crawlers render (they ignore SVG), self-contained with no external requests. |
| Passwords | The CLI encrypts locally: PBKDF2-HMAC-SHA256 (600k iterations) + AES-256-GCM. The server stores only {salt, iv, ciphertext}. The viewer serves an unlock shell that decrypts in the browser and renders the result inside a sandboxed iframe. The password never leaves the client. |
| Auto-update | The Recipe records scope, watch, and autoUpdate; Manifest v2 keeps the publication snapshot. artifact.mjs status reports stale watched artifacts, while the optional Stop-hook path only surfaces opted-in entries. Agents update Recipe fragments or ack reviewed drift. |
| Markdown | Rendered client-side (vendored marked, inlined — no CDN), so encrypted Markdown works without the server ever seeing plaintext. |
POST /api/artifacts { content, favicon, title?, description?, format?, label?, encrypted?, channel? }
→ 201 { id, url, writeToken, version, channel? }
PUT /api/artifacts/:id same fields + baseVersion?/force? (Bearer writeToken or channel token)
GET /api/artifacts/:id metadata + version history
GET /api/artifacts/:id/raw stored content (?v=N)
DELETE /api/artifacts/:id (Bearer writeToken)
GET /a/:id rendered page (?v=N)
encrypted is { salt, iv, iterations } (all base64/int) with base64
ciphertext as content. channel is a channel token (ch_...) that targets
the artifact already bound to that channel, or binds a new one on first use.
Max content size 4 MiB.
sandbox directive
(opaque origin — no cookies, no storage, no same-origin API calls) plus
default-src 'none', connect-src 'none', X-Content-Type-Options: nosniff and Referrer-Policy: no-referrer.*.workers.dev is on the Public Suffix List, isolating your instance from
other sites.--password for anything sensitive; title/favicon metadata stays
plaintext.CREATE_TOKEN) lets anyone with the URL create pages.
Set the secret for anything public-facing.pnpm test # Worker integration tests (vitest + workerd)
pnpm test:cli # skill CLI tests
pnpm typecheck
pnpm check # biome lint + format
BDD scenarios live in tests/features/; the architecture decision record in
docs/architecture.md.
MIT licensed.
1000+ skills curated from Anthropic, Vercel, Stripe, and other engineering teams
Agent harness performance optimization with skills, instincts, memory, and security
Design enforcement with memory — keeps your UI consistent across a project
Detects 37 AI writing patterns and rewrites text with human rhythm across 5 voice profiles