Skip to content

Instantly share code, notes, and snippets.

@ericboehs
Created February 23, 2026 16:01
Show Gist options
  • Select an option

  • Save ericboehs/1dd34d61540272a37dbe6e9d2aba60dd to your computer and use it in GitHub Desktop.

Select an option

Save ericboehs/1dd34d61540272a37dbe6e9d2aba60dd to your computer and use it in GitHub Desktop.
Convert Claude Desktop JSX artifacts into standalone HTML files that run directly in the browser
#!/usr/bin/env bash
# Converts a Claude Desktop JSX artifact into a standalone HTML file
# that runs directly in the browser via CDN-loaded React + Babel.
#
# Usage: claude-jsx-to-html input.jsx [output.html]
# If output is omitted, writes to input.html alongside the .jsx file.
set -euo pipefail
if [[ $# -lt 1 ]]; then
echo "Usage: claude-jsx-to-html input.jsx [output.html]"
exit 1
fi
INPUT="$1"
if [[ ! -f "$INPUT" ]]; then
echo "Error: File not found: $INPUT"
exit 1
fi
OUTPUT="${2:-${INPUT%.jsx}.html}"
# Extract the default export component name
COMPONENT=$(grep -oE 'export default function ([A-Za-z_][A-Za-z0-9_]*)' "$INPUT" | head -1 | awk '{print $NF}')
if [[ -z "$COMPONENT" ]]; then
# Try: export default ComponentName (at end of file)
COMPONENT=$(grep -oE 'export default ([A-Z][A-Za-z0-9_]*)' "$INPUT" | head -1 | awk '{print $NF}')
fi
if [[ -z "$COMPONENT" ]]; then
echo "Error: Could not find 'export default function ComponentName' in $INPUT"
exit 1
fi
# Extract the title from the component name (add spaces before capitals)
TITLE=$(echo "$COMPONENT" | sed 's/\([a-z]\)\([A-Z]\)/\1 \2/g')
# Collect all imported package names (excluding react/react-dom)
PACKAGES=()
while IFS= read -r pkg; do
[[ "$pkg" == "react" || "$pkg" == "react-dom" || "$pkg" == "react-dom/client" ]] && continue
PACKAGES+=("$pkg")
done < <(grep "^import " "$INPUT" | grep -oE "from '[^']+'" | sed "s/from '//;s/'//")
# Build importmap entries for third-party packages
IMPORTMAP_EXTRAS=""
for pkg in "${PACKAGES[@]}"; do
IMPORTMAP_EXTRAS+="$(printf '\n "%s": "https://esm.sh/%s?external=react",' "$pkg" "$pkg")"
done
# Remove trailing comma
IMPORTMAP_EXTRAS="${IMPORTMAP_EXTRAS%,}"
# Process the JSX: strip imports, fix export default
JSX_BODY=$(sed \
-e '/^import .* from /d' \
-e 's/^export default function /function /' \
-e 's/^export default //' \
"$INPUT")
cat > "$OUTPUT" << 'HTMLHEAD'
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
HTMLHEAD
echo " <title>${TITLE}</title>" >> "$OUTPUT"
cat >> "$OUTPUT" << HTMLIMPORTMAP
<script src="https://cdn.tailwindcss.com"></script>
<script type="importmap">
{
"imports": {
"react": "https://esm.sh/react@18.3.1",
"react/jsx-runtime": "https://esm.sh/react@18.3.1/jsx-runtime",
"react-dom/client": "https://esm.sh/react-dom@18.3.1/client"${IMPORTMAP_EXTRAS:+,$IMPORTMAP_EXTRAS}
}
}
</script>
<script src="https://unpkg.com/@babel/standalone@7/babel.min.js"></script>
<style>
html, body, #root { margin: 0; padding: 0; height: 100%; }
</style>
</head>
<body>
<div id="root"></div>
<script type="text/babel" data-type="module">
import React, { useState, useEffect, useRef, useCallback, useMemo } from 'react';
import { createRoot } from 'react-dom/client';
HTMLIMPORTMAP
# Re-add the non-react import lines so the module imports resolve
grep "^import " "$INPUT" | grep -v "from 'react'" | grep -v "from 'react-dom" >> "$OUTPUT" || true
# Write the processed JSX body
echo "" >> "$OUTPUT"
echo "$JSX_BODY" >> "$OUTPUT"
cat >> "$OUTPUT" << HTMLFOOT
// Mount the app
const root = createRoot(document.getElementById('root'));
root.render(<${COMPONENT} />);
</script>
</body>
</html>
HTMLFOOT
echo "Created: $OUTPUT"
echo "Component: $COMPONENT"
echo "Packages: ${PACKAGES[*]:-none}"
@ericboehs
Copy link
Author

claude-jsx-to-html

Convert Claude Desktop JSX artifacts into standalone HTML files that run directly in the browser — no build tools, no npm install, just open the file.

Features

  • Auto-detects the default export component name
  • Auto-discovers third-party packages from import lines and maps them via esm.sh CDN
  • Includes React 18, Tailwind CSS (Play CDN), and Babel standalone for in-browser JSX transpilation
  • Zero config — just point it at a .jsx file

Installation

curl -o ~/bin/claude-jsx-to-html https://gist.githubusercontent.com/ericboehs/1dd34d61540272a37dbe6e9d2aba60dd/raw/claude-jsx-to-html
chmod +x ~/bin/claude-jsx-to-html

Make sure ~/bin is in your $PATH.

Dependencies

  • bash, sed, grep, awk (standard Unix tools)
  • An internet connection (CDN dependencies load at runtime in the browser)

Usage

# Convert to HTML (outputs input.html next to the .jsx)
claude-jsx-to-html ~/Downloads/my-artifact.jsx

# Specify a custom output path
claude-jsx-to-html ~/Downloads/my-artifact.jsx ~/presentations/demo.html

# Then just open it
open ~/Downloads/my-artifact.html

How It Works

  1. Parses import statements to find third-party packages (e.g., lucide-react, recharts)
  2. Strips import/export lines from the JSX source
  3. Generates an HTML file with:
    • An importmap pointing packages to esm.sh CDN
    • Babel standalone <script type="text/babel" data-type="module"> for in-browser JSX transpilation
    • Tailwind CSS Play CDN
    • React 18 via esm.sh
  4. Mounts the detected component into a #root div

Supported Patterns

  • export default function ComponentName() { ... }
  • export default ComponentName (at end of file)
  • Any npm package imported via from 'package-name' gets added to the importmap automatically

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment