Web Artifacts Builder
Produce single-file HTML artifacts that run in any browser without a build step. Adapted from Anthropic's web-artifacts-builder skill.
When to use
- Dashboards or data viz the user wants to interact with.
- Calculators, converters, mini-tools.
- Explorable explanations (component playground, charting demo).
- Interactive mockups for prototyping UI ideas.
When NOT to use
- Static text-only output → use markdown or HTML directly.
- Anything that needs a backend or persistent storage → use a real Next.js / Express setup.
- Anything > 1500 lines → split into a real project.
Template
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{Title}}</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body class="bg-zinc-50">
<div id="root"></div>
<script type="text/babel" data-presets="react,env">
const { useState, useEffect, useMemo } = React
function App() {
const [count, setCount] = useState(0)
return (
<div className="max-w-2xl mx-auto p-8">
<h1 className="text-3xl font-bold mb-4">Hello</h1>
<button
className="px-4 py-2 rounded bg-zinc-900 text-white hover:bg-zinc-700"
onClick={() => setCount(c => c + 1)}
>
Clicked {count}
</button>
</div>
)
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />)
</script>
</body>
</html>
Adding shadcn-style components
For shadcn/ui, port the Tailwind class patterns directly — don't try to import the package (no build step). Common patterns:
// Button
<button className="inline-flex items-center justify-center rounded-md text-sm font-medium
bg-zinc-900 text-zinc-50 hover:bg-zinc-900/90 h-10 px-4 py-2">Click</button>
// Card
<div className="rounded-lg border bg-white text-zinc-950 shadow-sm">
<div className="p-6">...</div>
</div>
// Input
<input className="flex h-10 w-full rounded-md border border-zinc-200 bg-white px-3 py-2 text-sm
focus:outline-none focus:ring-2 focus:ring-zinc-950" />
Charting / 3rd party libs
Load from CDN inside <head>:
- Charts:
https://unpkg.com/recharts/umd/Recharts.js - Icons:
https://unpkg.com/lucide@latest/dist/umd/lucide.js - Math:
https://unpkg.com/mathjs@latest/lib/browser/math.js
Best practices
- One file. No imports of local files. Everything CDN or inline.
- Use Tailwind utility classes — no custom CSS unless absolutely needed.
- Keep state minimal. If it gets complex, add
useReducer. - Test by opening the file in a browser before delivering.
- Add a viewport meta tag for mobile.
Output
Write the HTML to a file (e.g. /tmp/artifact.html) so the user can open it locally, or paste it inline if the chat UI renders HTML artifacts.