`); const [isLoading, setIsLoading] = useState(false); const [activeTab, setActiveTab] = useState('chat'); const [previewKey, setPreviewKey] = useState(0); const messagesEndRef = useRef(null); const iframeRef = useRef(null); const scrollToBottom = () => { messagesEndRef.current?.scrollIntoView({ behavior: "smooth" }); }; useEffect(scrollToBottom, [messages]); const updatePreview = () => { setPreviewKey(prev => prev + 1); setTimeout(() => { if (iframeRef.current) { const blob = new Blob([code], { type: 'text/html' }); const url = URL.createObjectURL(blob); iframeRef.current.src = url; } }, 100); }; useEffect(() => { updatePreview(); }, [code]); const sendMessage = async () => { if (!inputMessage.trim()) return; const userMessage = { id: Date.now(), type: 'user', content: inputMessage, timestamp: new Date() }; setMessages(prev => [...prev, userMessage]); setIsLoading(true); setInputMessage(''); try { // Prepare conversation history const conversationHistory = [...messages, userMessage].map(msg => ({ role: msg.type === 'user' ? 'user' : 'assistant', content: msg.content })); const prompt = ` You are a software development assistant. You help users develop code and provide HTML, CSS, JavaScript code examples. Current code: \`\`\`html ${code} \`\`\` Conversation history: ${JSON.stringify(conversationHistory)} Based on the user's latest message: 1. If code changes are requested, provide the new code in JSON format 2. If they're just asking questions, respond normally JSON format (only when code changes are requested): { "response": "Explanation text", "code": "New HTML code here", "hasCode": true } Normal response format: { "response": "Normal response text", "hasCode": false } Your entire response must be valid JSON only, don't add anything else. `; const response = await window.claude.complete(prompt); let parsedResponse; try { parsedResponse = JSON.parse(response); } catch (e) { parsedResponse = { response: response, hasCode: false }; } const assistantMessage = { id: Date.now() + 1, type: 'assistant', content: parsedResponse.response, timestamp: new Date(), hasCode: parsedResponse.hasCode }; setMessages(prev => [...prev, assistantMessage]); // If there's a code update, update the code if (parsedResponse.hasCode && parsedResponse.code) { setCode(parsedResponse.code); } } catch (error) { console.error('Claude API error:', error); const errorMessage = { id: Date.now() + 1, type: 'assistant', content: 'Sorry, an error occurred. Please try again.', timestamp: new Date(), isError: true }; setMessages(prev => [...prev, errorMessage]); } finally { setIsLoading(false); } }; const handleKeyPress = (e) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); sendMessage(); } }; const clearChat = () => { setMessages([]); }; const copyCode = async () => { try { await navigator.clipboard.writeText(code); alert('Code copied to clipboard!'); } catch (err) { console.error('Copy error:', err); } }; const downloadCode = () => { const blob = new Blob([code], { type: 'text/html' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'index.html'; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); }; const quickPrompts = [ "Add a button that changes colors when clicked", "Create an animated card design", "Build a to-do list application", "Add a number guessing game", "Create a responsive navigation bar", "Add a modal popup" ]; return (
{/* Header */}

Claude Live Coding Chat

{/* Left Panel - Chat or Editor */}
{activeTab === 'chat' ? ( <> {/* Chat Messages */}
{messages.length === 0 ? (

Start coding with Claude!

Choose one of the quick suggestions below or write your own request.

{quickPrompts.map((prompt, index) => ( ))}
) : (
{messages.map((message) => (

{message.content}

{message.hasCode && (
✨ Code updated
)}
{message.timestamp.toLocaleTimeString()}
))}
)}
{/* Chat Input */}