Web Artifacts Builder
AnthropicOfficialPublished by Anthropic
- Skill
- Workflow
- Software development
- Apache-2.0
- Medium risk
- Has scripts
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
The Web Artifacts Builder provides a standardized process for creating sophisticated, self-contained HTML artifacts. By leveraging React, TypeScript, Tailwind CSS, and shadcn/ui, it enables developers to build complex frontend applications that include state management and routing. The workflow includes automated project initialization and a bundling process that inlines all assets into a single HTML file, making it suitable for direct presentation within Claude conversations.
What it does
- Initializes a pre-configured React project with TypeScript and Vite.
- Provides access to over 40 pre-installed shadcn/ui components.
- Configures path aliases and build settings for modern frontend development.
- Bundles complex multi-file projects into a single, self-contained HTML file.
- Inlines all CSS and JavaScript dependencies for seamless artifact rendering.
When to use it
- When building complex artifacts that require state management or routing.
- When you need to use shadcn/ui components in a Claude artifact.
- When a single-file JSX approach is insufficient for your project requirements.
- When you need to maintain a professional, non-generic design aesthetic.
Advantages
- Enables the creation of full-featured web applications within an artifact.
- Automates the complex bundling process required for multi-file projects.
- Ensures consistent project structure and dependency management.
- Reduces development overhead by providing a pre-configured environment.
Usage examples
- “Initialize a new project named dashboard-app using the web-artifacts-builder.”
- The agent runs the initialization script, setting up a React environment with Tailwind and shadcn/ui ready for development.
- “Bundle my current project into a single HTML file for sharing.”
- The agent executes the bundling script, which compiles the React app and inlines all assets into a single, shareable bundle.html file.
Install
1 of its files are not mirrored here, so install it from its source:
https://github.com/anthropics/skills/tree/2c5958ecac7cee2b583967a2c4981d0f4a75c579/skills/web-artifacts-builder
Documentation by Anthropic
Web Artifacts Builder
To build powerful frontend claude.ai artifacts, follow these steps:
Initialize the frontend repo using
scripts/init-artifact.shDevelop your artifact by editing the generated code
Bundle all code into a single HTML file using
scripts/bundle-artifact.shDisplay artifact to user
(Optional) Test the artifact
Stack: React 18 + TypeScript + Vite + Parcel (bundling) + Tailwind CSS + shadcn/ui
Design & Style Guidelines
VERY IMPORTANT: To avoid what is often referred to as "AI slop", avoid using excessive centered layouts, purple gradients, uniform rounded corners, and Inter font.
Quick Start
Step 1: Initialize Project
Run the initialization script to create a new React project:
bash scripts/init-artifact.sh <project-name>
cd <project-name>This creates a fully configured project with:
✅ React + TypeScript (via Vite)
✅ Tailwind CSS 3.4.1 with shadcn/ui theming system
✅ Path aliases (
@/) configured✅ 40+ shadcn/ui components pre-installed
✅ All Radix UI dependencies included
✅ Parcel configured for bundling (via .parcelrc)
✅ Node 18+ compatibility (auto-detects and pins Vite version)
Step 2: Develop Your Artifact
To build the artifact, edit the generated files. See Common Development Tasks below for guidance.
Step 3: Bundle to Single HTML File
To bundle the React app into a single HTML artifact:
bash scripts/bundle-artifact.shThis creates bundle.html - a self-contained artifact with all JavaScript, CSS, and dependencies inlined. This file can be directly shared in Claude conversations as an artifact.
Requirements: Your project must have an index.html in the root directory.
What the script does:
Installs bundling dependencies (parcel, @parcel/config-default, parcel-resolver-tspaths, html-inline)
Creates
.parcelrcconfig with path alias supportBuilds with Parcel (no source maps)
Inlines all assets into single HTML using html-inline
Step 4: Share Artifact with User
Finally, share the bundled HTML file in conversation with the user so they can view it as an artifact.
Step 5: Testing/Visualizing the Artifact (Optional)
Note: This is a completely optional step. Only perform if necessary or requested.
To test/visualize the artifact, use available tools (including other Skills or built-in tools like Playwright or Puppeteer). In general, avoid testing the artifact upfront as it adds latency between the request and when the finished artifact can be seen. Test later, after presenting the artifact, if requested or if issues arise.
Reference
shadcn/ui components: https://ui.shadcn.com/docs/components
Files
- ATTRIBUTION.mdAdded by AutoGineer905 B
- LICENSE.txt11.1 KiB
- SKILL.md3.0 KiB
- scripts/bundle-artifact.shScript1.5 KiB
- scripts/init-artifact.shScript9.7 KiB
- scripts/shadcn-components.tar.gz(opens on GitHub)Not mirrored: opens on GitHub19.5 KiB
scripts/init-artifact.sh
#!/bin/bash
# Exit on error
set -e
# Detect Node version
NODE_VERSION=$(node -v | cut -d'v' -f2 | cut -d'.' -f1)
echo "🔍 Detected Node.js version: $NODE_VERSION"
if [ "$NODE_VERSION" -lt 18 ]; then
echo "❌ Error: Node.js 18 or higher is required"
echo " Current version: $(node -v)"
exit 1
fi
# Set Vite version based on Node version
if [ "$NODE_VERSION" -ge 20 ]; then
VITE_VERSION="latest"
echo "✅ Using Vite latest (Node 20+)"
else
VITE_VERSION="5.4.11"
echo "✅ Using Vite $VITE_VERSION (Node 18 compatible)"
fi
# Detect OS and set sed syntax
if [[ "$OSTYPE" == "darwin"* ]]; then
SED_INPLACE="sed -i ''"
else
SED_INPLACE="sed -i"
fi
# Check if pnpm is installed
if ! command -v pnpm &> /dev/null; then
echo "📦 pnpm not found. Installing pnpm..."
npm install -g pnpm
fi
# Check if project name is provided
if [ -z "$1" ]; then
echo "❌ Usage: ./create-react-shadcn-complete.sh <project-name>"
exit 1
fi
PROJECT_NAME="$1"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
COMPONENTS_TARBALL="$SCRIPT_DIR/shadcn-components.tar.gz"
# Check if components tarball exists
if [ ! -f "$COMPONENTS_TARBALL" ]; then
echo "❌ Error: shadcn-components.tar.gz not found in script directory"
echo " Expected location: $COMPONENTS_TARBALL"
exit 1
fi
echo "🚀 Creating new React + Vite project: $PROJECT_NAME"
# Create new Vite project (always use latest create-vite, pin vite version later)
pnpm create vite "$PROJECT_NAME" --template react-ts
# Navigate into project directory
cd "$PROJECT_NAME"
echo "🧹 Cleaning up Vite template..."
$SED_INPLACE '/<link rel="icon".*vite\.svg/d' index.html
$SED_INPLACE 's/<title>.*<\/title>/<title>'"$PROJECT_NAME"'<\/title>/' index.html
echo "📦 Installing base dependencies..."
pnpm install
# Pin Vite version for Node 18
if [ "$NODE_VERSION" -lt 20 ]; then
echo "📌 Pinning Vite to $VITE_VERSION for Node 18 compatibility..."
pnpm add -D vite@$VITE_VERSION
fi
echo "📦 Installing Tailwind CSS and dependencies..."
pnpm install -D [email protected] postcss autoprefixer @types/node tailwindcss-animate
pnpm install class-variance-authority clsx tailwind-merge lucide-react next-themes
echo "⚙️ Creating Tailwind and PostCSS configuration..."
cat > postcss.config.js << 'EOF'
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
EOF
echo "📝 Configuring Tailwind with shadcn theme..."
cat > tailwind.config.js << 'EOF'
/** @type {import('tailwindcss').Config} */
module.exports = {
darkMode: ["class"],
content: [
"./index.html",
"./src/**/*.{js,ts,jsx,tsx}",
],
theme: {
extend: {
colors: {
border: "hsl(var(--border))",
input: "hsl(var(--input))",
ring: "hsl(var(--ring))",
background: "hsl(var(--background))",
foreground: "hsl(var(--foreground))",
primary: {
DEFAULT: "hsl(var(--primary))",
foreground: "hsl(var(--primary-foreground))",
},
secondary: {
DEFAULT: "hsl(var(--secondary))",
foreground: "hsl(var(--secondary-foreground))",
},
destructive: {
DEFAULT: "hsl(var(--destructive))",
foreground: "hsl(var(--destructive-foreground))",
},
muted: {
DEFAULT: "hsl(var(--muted))",
foreground: "hsl(var(--muted-foreground))",
},
accent: {
DEFAULT: "hsl(var(--accent))",
foreground: "hsl(var(--accent-foreground))",
},
popover: {
DEFAULT: "hsl(var(--popover))",
foreground: "hsl(var(--popover-foreground))",
},
card: {
DEFAULT: "hsl(var(--card))",
foreground: "hsl(var(--card-foreground))",
},
},
borderRadius: {
lg: "var(--radius)",
md: "calc(var(--radius) - 2px)",
sm: "calc(var(--radius) - 4px)",
},
keyframes: {
"accordion-down": {
from: { height: "0" },
to: { height: "var(--radix-accordion-content-height)" },
},
"accordion-up": {
from: { height: "var(--radix-accordion-content-height)" },
to: { height: "0" },
},
},
animation: {
"accordion-down": "accordion-down 0.2s ease-out",
"accordion-up": "accordion-up 0.2s ease-out",
},
},
},
plugins: [require("tailwindcss-animate")],
}
EOF
# Add Tailwind directives and CSS variables to index.css
echo "🎨 Adding Tailwind directives and CSS variables..."
cat > src/index.css << 'EOF'
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 0 0% 3.9%;
--card: 0 0% 100%;
--card-foreground: 0 0% 3.9%;
--popover: 0 0% 100%;
--popover-foreground: 0 0% 3.9%;
--primary: 0 0% 9%;
--primary-foreground: 0 0% 98%;
--secondary: 0 0% 96.1%;
--secondary-foreground: 0 0% 9%;
--muted: 0 0% 96.1%;
--muted-foreground: 0 0% 45.1%;
--accent: 0 0% 96.1%;
--accent-foreground: 0 0% 9%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 0 0% 98%;
--border: 0 0% 89.8%;
--input: 0 0% 89.8%;
--ring: 0 0% 3.9%;
--radius: 0.5rem;
}
.dark {
--background: 0 0% 3.9%;
--foreground: 0 0% 98%;
--card: 0 0% 3.9%;
--card-foreground: 0 0% 98%;
--popover: 0 0% 3.9%;
--popover-foreground: 0 0% 98%;
--primary: 0 0% 98%;
--primary-foreground: 0 0% 9%;
--secondary: 0 0% 14.9%;
--secondary-foreground: 0 0% 98%;
--muted: 0 0% 14.9%;
--muted-foreground: 0 0% 63.9%;
--accent: 0 0% 14.9%;
--accent-foreground: 0 0% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 0 0% 98%;
--border: 0 0% 14.9%;
--input: 0 0% 14.9%;
--ring: 0 0% 83.1%;
}
}
@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}
EOF
# Add path aliases to tsconfig.json
echo "🔧 Adding path aliases to tsconfig.json..."
node -e "
const fs = require('fs');
const config = JSON.parse(fs.readFileSync('tsconfig.json', 'utf8'));
config.compilerOptions = config.compilerOptions || {};
config.compilerOptions.baseUrl = '.';
config.compilerOptions.paths = { '@/*': ['./src/*'] };
fs.writeFileSync('tsconfig.json', JSON.stringify(config, null, 2));
"
# Add path aliases to tsconfig.app.json
echo "🔧 Adding path aliases to tsconfig.app.json..."
node -e "
const fs = require('fs');
const path = 'tsconfig.app.json';
const content = fs.readFileSync(path, 'utf8');
// Remove comments manually
const lines = content.split('\n').filter(line => !line.trim().startsWith('//'));
const jsonContent = lines.join('\n');
const config = JSON.parse(jsonContent.replace(/\/\*[\s\S]*?\*\//g, '').replace(/,(\s*[}\]])/g, '\$1'));
config.compilerOptions = config.compilerOptions || {};
config.compilerOptions.baseUrl = '.';
config.compilerOptions.paths = { '@/*': ['./src/*'] };
fs.writeFileSync(path, JSON.stringify(config, null, 2));
"
# Update vite.config.ts
echo "⚙️ Updating Vite configuration..."
cat > vite.config.ts << 'EOF'
import path from "path";
import react from "@vitejs/plugin-react";
import { defineConfig } from "vite";
export default defineConfig({
plugins: [react()],
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
},
},
});
EOF
# Install all shadcn/ui dependencies
echo "📦 Installing shadcn/ui dependencies..."
pnpm install @radix-ui/react-accordion @radix-ui/react-aspect-ratio @radix-ui/react-avatar @radix-ui/react-checkbox @radix-ui/react-collapsible @radix-ui/react-context-menu @radix-ui/react-dialog @radix-ui/react-dropdown-menu @radix-ui/react-hover-card @radix-ui/react-label @radix-ui/react-menubar @radix-ui/react-navigation-menu @radix-ui/react-popover @radix-ui/react-progress @radix-ui/react-radio-group @radix-ui/react-scroll-area @radix-ui/react-select @radix-ui/react-separator @radix-ui/react-slider @radix-ui/react-slot @radix-ui/react-switch @radix-ui/react-tabs @radix-ui/react-toast @radix-ui/react-toggle @radix-ui/react-toggle-group @radix-ui/react-tooltip
pnpm install sonner cmdk vaul embla-carousel-react react-day-picker react-resizable-panels date-fns react-hook-form @hookform/resolvers zod
# Extract shadcn components from tarball
echo "📦 Extracting shadcn/ui components..."
tar -xzf "$COMPONENTS_TARBALL" -C src/
# Create components.json for reference
echo "📝 Creating components.json config..."
cat > components.json << 'EOF'
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "default",
"rsc": false,
"tsx": true,
"tailwind": {
"config": "tailwind.config.js",
"css": "src/index.css",
"baseColor": "slate",
"cssVariables": true,
"prefix": ""
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
}
}
EOF
echo "✅ Setup complete! You can now use Tailwind CSS and shadcn/ui in your project."
echo ""
echo "📦 Included components (40+ total):"
echo " - accordion, alert, aspect-ratio, avatar, badge, breadcrumb"
echo " - button, calendar, card, carousel, checkbox, collapsible"
echo " - command, context-menu, dialog, drawer, dropdown-menu"
echo " - form, hover-card, input, label, menubar, navigation-menu"
echo " - popover, progress, radio-group, resizable, scroll-area"
echo " - select, separator, sheet, skeleton, slider, sonner"
echo " - switch, table, tabs, textarea, toast, toggle, toggle-group, tooltip"
echo ""
echo "To start developing:"
echo " cd $PROJECT_NAME"
echo " pnpm dev"
echo ""
echo "📚 Import components like:"
echo " import { Button } from '@/components/ui/button'"
echo " import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card'"
echo " import { Dialog, DialogContent, DialogTrigger } from '@/components/ui/dialog'"
Requirements and compatibility
Written for: Claude Code, Claude apps
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Security
What our scanner noticed· Medium risk
- Archive files
- Scripts that your agent may run
This skill includes scripts that your agent may run. Read them before you use it.
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Published by
- Anthropic
- Publisher
- Anthropic (Official)
- Source
- anthropics/skills · skills/web-artifacts-builder · commit 2c5958e
- Licence
- Apache License 2.0 (redistribution allowed)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by Anthropic.
Get it from the source
1 of this skill’s files are not mirrored here, so there is no ZIP. Get the complete skill from its source: anthropics/skills