AI Code & Component Playground
Interactive online HTML, CSS, and JS code editor sandbox with live instant iframe preview, Tailwind CDN support, console logs, and ZIP exporter.
AI Code & Component Playground
⚡ Executive Project Overview
The AI Code & Component Playground is a modern, high-performance web-based code sandbox designed for developers, UI/UX designers, and students to build, test, and prototype HTML5, CSS3, and JavaScript components in real-time. Built with pure client-side architecture, it eliminates the latency of traditional server-rendered editors, offering immediate 60 FPS live preview updates as you type.
Real-Time Multi-Tab Editor
Independent tabs for HTML, CSS, and JavaScript with line numbers, tab-key indentation support, and debounced auto-rendering into an isolated iframe sandbox.
Tailwind CSS & Preset Library
Built-in toggle for Tailwind CSS v3 Play CDN along with pre-loaded UI presets including Glassmorphic Cards, Neon Buttons, AI Chat Drawers, and Interactive Counters.
Integrated Console Log Interceptor
Captures `console.log()` calls and uncaught JavaScript runtime errors directly inside an embedded console output drawer with timestamps for instant debugging.
1-Click Single File Export
Instantly bundle your HTML structure, custom CSS styles, Tailwind dependencies, and JS scripts into a standalone `.html` file ready for deployment or sharing.
Key Advantages & Benefits
- Zero Server Latency: Runs 100% locally in your web browser memory without sending user code to external API servers.
- Isolated Iframe Security: Code execution takes place inside a sandboxed iframe to prevent global scope contamination.
- Fully Responsive Layout: Flexible split-pane interface optimized for desktop monitors, laptops, and tablets.
- Free Open-Source Code: Full source code download available with standard MIT license for personal and commercial projects.
🛠️ How to Use the AI Component Playground
- Select a preset from the top toolbar dropdown to load starter code (e.g. Glassmorphic Card or AI Chat).
- Switch between the HTML, CSS, and JavaScript tabs to edit your code.
- Enable or disable the Tailwind CSS toggle depending on your project requirements.
- View your changes automatically update in real time in the live render viewport.
- Click Export HTML to save the complete standalone component to your computer.
<!DOCTYPE html>
<html lang="en" class="h-full dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI Code & Component Playground - Live Web Sandbox</title>
<!-- Fonts & Icons -->
<link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500;600&family=Inter:wght@400;500;600;700;800&family=Outfit:wght@600;700;800&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
<!-- Tailwind CSS CDN -->
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = {
darkMode: 'class',
theme: {
extend: {
fontFamily: {
sans: ['Inter', 'sans-serif'],
outfit: ['Outfit', 'sans-serif'],
mono: ['Fira Code', 'monospace']
}
}
}
}
</script>
<style>
body { margin: 0; padding: 0; height: 100vh; overflow: hidden; background-color: #0b0f17; }
.code-textarea {
tab-size: 2;
font-family: 'Fira Code', monospace;
resize: none;
outline: none;
line-height: 1.5;
}
.code-textarea::-webkit-scrollbar { width: 6px; height: 6px; }
.code-textarea::-webkit-scrollbar-track { background: rgba(15, 23, 42, 0.6); }
.code-textarea::-webkit-scrollbar-thumb { background: rgba(56, 189, 248, 0.2); border-radius: 4px; }
.code-textarea::-webkit-scrollbar-thumb:hover { background: rgba(56, 189, 248, 0.4); }
</style>
</head>
<body class="h-full text-slate-100 flex flex-col font-sans select-none">
<!-- Header Toolbar -->
<header class="h-14 bg-slate-900/90 backdrop-blur-md border-b border-slate-800/80 px-4 flex items-center justify-between shrink-0 z-30">
<div class="flex items-center gap-3">
<div class="w-8 h-8 rounded-lg bg-gradient-to-tr from-cyan-500 to-blue-600 flex items-center justify-center text-slate-950 font-outfit font-extrabold text-base shadow-lg shadow-cyan-500/20">
⚡
</div>
<div>
<h1 class="font-outfit font-bold text-sm text-white tracking-wide">AI Code & Component Playground</h1>
<p class="text-[10px] text-cyan-400 font-mono">Live HTML5 / CSS3 / JS Interactive Web Sandbox</p>
</div>
</div>
<!-- Presets & Actions -->
<div class="flex items-center gap-2">
<!-- Preset Component Selector -->
<select id="presetSelect" class="bg-slate-950 border border-slate-800 text-slate-300 text-xs font-semibold rounded-lg px-3 py-1.5 focus:outline-none focus:border-cyan-500 transition">
<option value="glass-card">Preset: Glassmorphism Card</option>
<option value="glowing-btn">Preset: Neon Glowing Button</option>
<option value="ai-chat">Preset: AI Chat Widget</option>
<option value="counter">Preset: Interactive Counter</option>
</select>
<!-- Library Toggles -->
<label class="inline-flex items-center gap-1.5 bg-slate-950/80 border border-slate-800/80 px-2.5 py-1 rounded-lg text-xs font-semibold text-slate-300 cursor-pointer hover:border-cyan-500/40 transition">
<input type="checkbox" id="tailwindToggle" checked class="rounded border-slate-700 text-cyan-500 focus:ring-0">
<span>Tailwind CSS</span>
</label>
<button id="runBtn" class="px-3.5 py-1.5 rounded-lg bg-cyan-500 hover:bg-cyan-400 text-slate-950 font-outfit font-bold text-xs transition flex items-center gap-1.5 shadow-md shadow-cyan-500/20">
<i class="fa-solid fa-play"></i>
<span>Run</span>
</button>
<button id="downloadBtn" class="px-3.5 py-1.5 rounded-lg bg-slate-800 hover:bg-slate-700 text-white font-outfit font-bold text-xs transition flex items-center gap-1.5 border border-slate-700">
<i class="fa-solid fa-download"></i>
<span>Export HTML</span>
</button>
</div>
</header>
<!-- Main Playground Body -->
<div class="flex-1 flex flex-col md:flex-row min-h-0 overflow-hidden relative">
<!-- Left Column: Code Editors (HTML, CSS, JS) -->
<div class="w-full md:w-1/2 flex flex-col border-r border-slate-800/80 bg-slate-950 shrink-0">
<!-- Tab Switcher Header -->
<div class="flex items-center bg-slate-900/60 border-b border-slate-800/80 text-xs font-bold shrink-0">
<button id="tabHtml" class="tab-btn px-4 py-2.5 text-cyan-400 border-b-2 border-cyan-500 bg-slate-900/80 flex items-center gap-2 transition">
<i class="fa-brands fa-html5 text-orange-500"></i> HTML
</button>
<button id="tabCss" class="tab-btn px-4 py-2.5 text-slate-400 hover:text-white border-b-2 border-transparent flex items-center gap-2 transition">
<i class="fa-brands fa-css3-alt text-blue-500"></i> CSS
</button>
<button id="tabJs" class="tab-btn px-4 py-2.5 text-slate-400 hover:text-white border-b-2 border-transparent flex items-center gap-2 transition">
<i class="fa-brands fa-js text-yellow-400"></i> JavaScript
</button>
<div class="ml-auto pr-3 text-[11px] font-mono text-slate-500">
<span id="autoRunStatus" class="inline-flex items-center gap-1 text-emerald-400">
<span class="w-1.5 h-1.5 rounded-full bg-emerald-400 animate-ping"></span> Live Sync
</span>
</div>
</div>
<!-- Editor Textareas Container -->
<div class="flex-1 relative bg-slate-950 overflow-hidden">
<!-- HTML Editor -->
<textarea id="htmlEditor" class="code-textarea absolute inset-0 w-full h-full p-4 bg-slate-950 text-slate-200 text-xs leading-relaxed border-0" spellcheck="false" placeholder="<!-- Enter HTML Here -->"></textarea>
<!-- CSS Editor -->
<textarea id="cssEditor" class="code-textarea absolute inset-0 w-full h-full p-4 bg-slate-950 text-slate-200 text-xs leading-relaxed border-0 hidden" spellcheck="false" placeholder="/* Enter CSS Here */"></textarea>
<!-- JS Editor -->
<textarea id="jsEditor" class="code-textarea absolute inset-0 w-full h-full p-4 bg-slate-950 text-slate-200 text-xs leading-relaxed border-0 hidden" spellcheck="false" placeholder="// Enter JavaScript Here"></textarea>
</div>
</div>
<!-- Right Column: Live Iframe Preview & Console Output -->
<div class="w-full md:w-1/2 flex flex-col bg-slate-900 shrink-0">
<!-- Preview Sub-header -->
<div class="h-9 bg-slate-950/80 border-b border-slate-800/80 px-4 flex items-center justify-between text-xs font-bold shrink-0">
<span class="text-slate-400 flex items-center gap-2">
<span class="w-2 h-2 rounded-full bg-cyan-400 animate-pulse"></span> Live Render Viewport
</span>
<div class="flex items-center gap-2">
<button id="clearConsoleBtn" class="text-[11px] font-mono text-slate-400 hover:text-rose-400 transition">Clear Console</button>
<button id="fullscreenBtn" class="text-slate-400 hover:text-white transition" title="Toggle Fullscreen">
<i class="fa-solid fa-expand"></i>
</button>
</div>
</div>
<!-- Live Output Iframe Container -->
<div class="flex-1 bg-white relative overflow-hidden">
<iframe id="previewIframe" class="w-full h-full border-0 bg-slate-950"></iframe>
</div>
<!-- Mini Console Output Log Drawer -->
<div class="h-28 bg-slate-950 border-t border-slate-800/80 flex flex-col font-mono text-[11px] shrink-0">
<div class="h-6 bg-slate-900/60 border-b border-slate-800/80 px-3 flex items-center justify-between text-slate-400 font-sans font-bold text-[10px] tracking-wider uppercase">
<span>Console Logs & Output</span>
<span id="logCount" class="text-cyan-400 font-mono">0 logs</span>
</div>
<div id="consoleLogContainer" class="flex-1 p-3 space-y-1 overflow-y-auto text-slate-300 select-text">
<div class="text-slate-500 italic">[System] Sandbox initialized. Output logs will appear here...</div>
</div>
</div>
</div>
</div>
<!-- JavaScript Execution & Interactive Logic -->
<script>
const htmlEditor = document.getElementById('htmlEditor');
const cssEditor = document.getElementById('cssEditor');
const jsEditor = document.getElementById('jsEditor');
const previewIframe = document.getElementById('previewIframe');
const tailwindToggle = document.getElementById('tailwindToggle');
const presetSelect = document.getElementById('presetSelect');
const consoleLogContainer = document.getElementById('consoleLogContainer');
const logCount = document.getElementById('logCount');
let currentLogsCount = 0;
// Presets Library
const presets = {
'glass-card': {
html: `<div class="min-h-screen bg-slate-950 flex items-center justify-center p-6">
<div class="max-w-sm w-full bg-slate-900/80 backdrop-blur-xl border border-slate-800 rounded-3xl p-6 shadow-2xl text-center space-y-4 relative overflow-hidden group">
<div class="w-16 h-16 rounded-2xl bg-cyan-500/10 border border-cyan-500/20 text-cyan-400 flex items-center justify-center text-3xl mx-auto group-hover:scale-110 transition duration-300">
⚡
</div>
<h2 class="font-outfit font-extrabold text-2xl text-white">AI Component Card</h2>
<p class="text-slate-400 text-xs leading-relaxed">
A sleek glassmorphism UI card component created with Tailwind CSS and responsive micro-interactions.
</p>
<button onclick="triggerAction()" class="w-full py-3 rounded-xl bg-gradient-to-r from-cyan-500 to-blue-600 hover:from-cyan-400 hover:to-blue-500 text-slate-950 font-bold text-xs tracking-wider uppercase transition shadow-lg shadow-cyan-500/20">
Execute Action
</button>
</div>
</div>`,
css: `/* Custom CSS Glassmorphism Highlights */
body { font-family: 'Inter', sans-serif; }
.group:hover { border-color: rgba(6, 182, 212, 0.4); }`,
js: `function triggerAction() {
console.log("Action button clicked!");
alert("AI Component Interactive Action Triggered Successfully!");
}`
},
'glowing-btn': {
html: `<div class="min-h-screen bg-slate-950 flex items-center justify-center gap-4 p-6">
<button onclick="btnClick('Cyan')" class="glow-btn px-6 py-3 rounded-2xl bg-cyan-500 text-slate-950 font-bold text-xs uppercase tracking-wider transition hover:scale-105">
Glowing Cyan
</button>
<button onclick="btnClick('Purple')" class="glow-btn-purple px-6 py-3 rounded-2xl bg-purple-600 text-white font-bold text-xs uppercase tracking-wider transition hover:scale-105">
Neon Purple
</button>
</div>`,
css: `.glow-btn {
box-shadow: 0 0 20px rgba(6, 182, 212, 0.5);
}
.glow-btn-purple {
box-shadow: 0 0 20px rgba(168, 85, 247, 0.5);
}`,
js: `function btnClick(type) {
console.log(type + " glowing button activated!");
}`
},
'ai-chat': {
html: `<div class="min-h-screen bg-slate-950 flex items-center justify-center p-4">
<div class="w-full max-w-md bg-slate-900 border border-slate-800 rounded-3xl overflow-hidden shadow-2xl flex flex-col h-[400px]">
<div class="p-4 bg-slate-950 border-b border-slate-800 flex items-center gap-3">
<div class="w-3 h-3 rounded-full bg-emerald-400 animate-pulse"></div>
<span class="font-bold text-xs text-white">AI Assistant Chat</span>
</div>
<div id="chatMessages" class="flex-1 p-4 space-y-3 overflow-y-auto text-xs text-slate-300">
<div class="bg-slate-800/60 p-3 rounded-2xl max-w-[80%]">Hello! How can I assist your coding today?</div>
</div>
<div class="p-3 bg-slate-950 border-t border-slate-800 flex gap-2">
<input type="text" id="userInput" placeholder="Ask AI..." class="flex-1 bg-slate-900 border border-slate-800 text-xs rounded-xl px-3 py-2 text-white focus:outline-none focus:border-cyan-500">
<button onclick="sendMessage()" class="px-4 py-2 bg-cyan-500 text-slate-950 font-bold rounded-xl text-xs">Send</button>
</div>
</div>
</div>`,
css: `::-webkit-scrollbar { width: 4px; }
::-webkit-scrollbar-thumb { background: rgba(56,189,248,0.2); border-radius: 4px; }`,
js: `function sendMessage() {
const input = document.getElementById('userInput');
const text = input.value.trim();
if (!text) return;
const chat = document.getElementById('chatMessages');
chat.innerHTML += \`<div class="bg-cyan-500/10 border border-cyan-500/20 text-cyan-300 p-3 rounded-2xl max-w-[80%] ml-auto">\${text}</div>\`;
console.log("User query sent:", text);
input.value = '';
setTimeout(() => {
chat.innerHTML += \`<div class="bg-slate-800/60 p-3 rounded-2xl max-w-[80%]">Received "\${text}". AI Processing complete!</div>\`;
chat.scrollTop = chat.scrollHeight;
}, 600);
}`
},
'counter': {
html: `<div class="min-h-screen bg-slate-950 flex flex-col items-center justify-center p-6 text-center space-y-6">
<div class="p-8 rounded-3xl bg-slate-900 border border-slate-800 space-y-4 shadow-2xl">
<span class="text-xs font-bold uppercase tracking-wider text-cyan-400">Interactive Counter State</span>
<h1 id="countVal" class="text-6xl font-extrabold text-white font-mono">0</h1>
<div class="flex gap-3">
<button onclick="updateCount(-1)" class="px-5 py-2.5 rounded-xl bg-slate-800 hover:bg-slate-700 text-white font-bold text-sm">- Decrease</button>
<button onclick="updateCount(0)" class="px-5 py-2.5 rounded-xl bg-slate-800 hover:bg-slate-700 text-slate-400 font-bold text-sm">Reset</button>
<button onclick="updateCount(1)" class="px-5 py-2.5 rounded-xl bg-cyan-500 hover:bg-cyan-400 text-slate-950 font-bold text-sm">+ Increase</button>
</div>
</div>
</div>`,
css: `/* Counter Styling */`,
js: `let count = 0;
function updateCount(val) {
if (val === 0) count = 0;
else count += val;
document.getElementById('countVal').innerText = count;
console.log("Current count:", count);
}`
}
};
// Load Initial Preset
function loadPreset(key) {
if (presets[key]) {
htmlEditor.value = presets[key].html;
cssEditor.value = presets[key].css;
jsEditor.value = presets[key].js;
updateSandbox();
}
}
// Render Sandbox Output
function updateSandbox() {
const html = htmlEditor.value;
const css = cssEditor.value;
const js = jsEditor.value;
const useTailwind = tailwindToggle.checked;
const tailwindScript = useTailwind ? '<script src="https://cdn.tailwindcss.com"><\/script>' : '';
const source = `
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Outfit:wght@600;700;800&display=swap" rel="stylesheet">
${tailwindScript}
<style>
${css}
</style>
</head>
<body class="bg-slate-950 text-slate-100">
${html}
<script>
// Console Interception
const _log = console.log;
console.log = function(...args) {
_log(...args);
window.parent.postMessage({ type: 'CONSOLE_LOG', data: args.join(' ') }, '*');
};
window.onerror = function(msg, url, line) {
window.parent.postMessage({ type: 'CONSOLE_ERROR', data: 'Error: ' + msg + ' (Line ' + line + ')' }, '*');
};
${js}
<\/script>
</body>
</html>`;
const iframeDoc = previewIframe.contentDocument || previewIframe.contentWindow.document;
iframeDoc.open();
iframeDoc.write(source);
iframeDoc.close();
}
// Listen for Console Logs from Iframe
window.addEventListener('message', (event) => {
if (event.data && (event.data.type === 'CONSOLE_LOG' || event.data.type === 'CONSOLE_ERROR')) {
const isError = event.data.type === 'CONSOLE_ERROR';
const div = document.createElement('div');
div.className = isError ? 'text-rose-400 font-semibold' : 'text-cyan-300';
div.innerHTML = `<span class="text-slate-500">[' + new Date().toLocaleTimeString() + ']</span> ` + event.data.data;
consoleLogContainer.appendChild(div);
consoleLogContainer.scrollTop = consoleLogContainer.scrollHeight;
currentLogsCount++;
logCount.innerText = currentLogsCount + ' logs';
}
});
// Tab Switching Logic
const tabHtml = document.getElementById('tabHtml');
const tabCss = document.getElementById('tabCss');
const tabJs = document.getElementById('tabJs');
function switchTab(activeTab, showEditor) {
[tabHtml, tabCss, tabJs].forEach(t => {
t.classList.remove('text-cyan-400', 'border-cyan-500', 'bg-slate-900/80');
t.classList.add('text-slate-400', 'border-transparent');
});
activeTab.classList.add('text-cyan-400', 'border-cyan-500', 'bg-slate-900/80');
activeTab.classList.remove('text-slate-400', 'border-transparent');
[htmlEditor, cssEditor, jsEditor].forEach(e => e.classList.add('hidden'));
showEditor.classList.remove('hidden');
}
tabHtml.addEventListener('click', () => switchTab(tabHtml, htmlEditor));
tabCss.addEventListener('click', () => switchTab(tabCss, cssEditor));
tabJs.addEventListener('click', () => switchTab(tabJs, jsEditor));
// Auto-update on typing with debounce
let timer = null;
[htmlEditor, cssEditor, jsEditor].forEach(editor => {
editor.addEventListener('input', () => {
clearTimeout(timer);
timer = setTimeout(updateSandbox, 300);
});
});
tailwindToggle.addEventListener('change', updateSandbox);
presetSelect.addEventListener('change', (e) => loadPreset(e.target.value));
document.getElementById('runBtn').addEventListener('click', updateSandbox);
document.getElementById('clearConsoleBtn').addEventListener('click', () => {
consoleLogContainer.innerHTML = '<div class="text-slate-500 italic">[System] Console cleared.</div>';
currentLogsCount = 0;
logCount.innerText = '0 logs';
});
// Export as HTML File
document.getElementById('downloadBtn').addEventListener('click', () => {
const fullCode = `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Exported Component</title>
${tailwindToggle.checked ? '<script src="https://cdn.tailwindcss.com"><\/script>' : ''}
<style>
${cssEditor.value}
</style>
</head>
<body>
${htmlEditor.value}
<script>
${jsEditor.value}
<\/script>
</body>
</html>`;
const blob = new Blob([fullCode], { type: 'text/html' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'component-playground-export.html';
a.click();
URL.revokeObjectURL(url);
});
// Fullscreen Toggle
document.getElementById('fullscreenBtn').addEventListener('click', () => {
if (!document.fullscreenElement) {
previewIframe.requestFullscreen().catch(err => alert(err.message));
} else {
document.exitFullscreen();
}
});
// Init Default
loadPreset('glass-card');
</script>
</body>
</html>
/* Supports both Dark and Light mode via Tailwind class variant */
// Interactive scripts included inside demo view file
Related Projects
Interactive Drag & Drop Kanban Task Board
FeaturedA clean Trello-style Kanban board built with HTML5 HTML Drag and Drop API, color-coded task priorities, and local storage state persistence.
CSS Glassmorphism & Gradient Code Generator
FeaturedAn interactive visual CSS generator tool to tweak backdrop blur, opacity, transparency, and background gradients with instant 1-click code copying.