Anything / app.py
Holycanolies123's picture
Create app.py
1ea09f1 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>App Creator AI</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/highlight.js@11.7.0/lib/core.js"></script>
<script src="https://cdn.jsdelivr.net/npm/highlight.js@11.7.0/lib/languages/javascript.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/highlight.js@11.7.0/lib/languages/html.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/highlight.js@11.7.0/lib/languages/css.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/highlight.js@11.7.0/styles/github.css">
<style>
/* Custom scrollbar */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background: transparent;
}
::-webkit-scrollbar-thumb {
background: #5D5CDE;
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: #4a49b0;
}
/* Dark mode adjustments */
.dark .hljs {
background: #2d2d2d;
color: #ccc;
}
.dark .hljs-tag,
.dark .hljs-keyword {
color: #e78c45;
}
.dark .hljs-title,
.dark .hljs-class,
.dark .hljs-section {
color: #e7c547;
}
.dark .hljs-string {
color: #b9ca4a;
}
.dark .hljs-attr {
color: #70c0b1;
}
</style>
<script>
tailwind.config = {
darkMode: 'class',
theme: {
extend: {
colors: {
primary: '#5D5CDE',
'primary-dark': '#4a49b0',
'primary-light': '#7a79e6',
},
}
}
}
</script>
</head>
<body class="min-h-screen bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100 transition-colors duration-200">
<div class="container mx-auto px-4 py-6 max-w-6xl">
<header class="mb-8 text-center">
<h1 class="text-3xl font-bold text-primary dark:text-primary-light mb-2">App Creator AI</h1>
<p class="text-gray-600 dark:text-gray-400">Describe your app and I'll generate the code for you</p>
</header>
<main class="space-y-8">
<!-- App Description Input -->
<section class="space-y-4">
<div class="flex justify-between items-center">
<h2 class="text-xl font-semibold">1. Describe Your App</h2>
<div class="flex items-center space-x-2">
<label for="botSelect" class="text-sm">AI Model:</label>
<select id="botSelect" class="bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded-md px-3 py-1 text-base focus:outline-none focus:ring-2 focus:ring-primary">
<option value="Claude-3.7-Sonnet" selected>Claude-3.7-Sonnet</option>
<option value="GPT-4o">GPT-4o</option>
<option value="GPT-4o-mini">GPT-4o-mini</option>
</select>
</div>
</div>
<textarea id="appDescription" rows="5" placeholder="Describe the app you want to create in detail. For example: 'Create a to-do list app with the ability to add, remove, and mark tasks as complete. The app should have a clean design with a dark mode option.'" class="w-full p-3 text-base border border-gray-300 dark:border-gray-700 rounded-md bg-white dark:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-primary resize-y"></textarea>
<button id="generateBtn" class="w-full md:w-auto px-6 py-2 bg-primary hover:bg-primary-dark text-white font-medium rounded-md transition-colors duration-200 flex items-center justify-center">
<span id="generateBtnText">Generate App</span>
<svg id="generateBtnSpinner" class="animate-spin ml-2 h-5 w-5 text-white hidden" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
</button>
</section>
<!-- Results Section (hidden initially) -->
<section id="resultsSection" class="hidden space-y-6">
<div class="border-t border-gray-300 dark:border-gray-700 pt-6">
<h2 class="text-xl font-semibold mb-4">2. Generated App</h2>
<!-- Tabs -->
<div class="flex border-b border-gray-300 dark:border-gray-700 mb-4">
<button id="previewTab" class="px-4 py-2 font-medium border-b-2 border-primary text-primary dark:text-primary-light">Preview</button>
<button id="codeTab" class="px-4 py-2 font-medium text-gray-600 dark:text-gray-400 hover:text-primary dark:hover:text-primary-light">Code</button>
</div>
<!-- Preview panel -->
<div id="previewPanel" class="bg-gray-100 dark:bg-gray-800 rounded-md p-4 min-h-[300px]">
<div class="bg-white dark:bg-gray-900 rounded-md w-full h-full min-h-[300px] border border-gray-300 dark:border-gray-700 overflow-hidden">
<iframe id="previewFrame" class="w-full h-[500px] border-none"></iframe>
</div>
</div>
<!-- Code panel -->
<div id="codePanel" class="hidden">
<div class="bg-gray-100 dark:bg-gray-800 rounded-md p-4">
<pre><code id="codeDisplay" class="language-html text-sm overflow-x-auto"></code></pre>
<button id="copyCodeBtn" class="mt-4 px-4 py-2 bg-gray-200 dark:bg-gray-700 hover:bg-gray-300 dark:hover:bg-gray-600 rounded-md text-sm font-medium transition-colors duration-200 flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" />
</svg>
Copy Code
</button>
</div>
</div>
</div>
</section>
<!-- Refinement Section (hidden initially) -->
<section id="refinementSection" class="hidden space-y-4 border-t border-gray-300 dark:border-gray-700 pt-6">
<h2 class="text-xl font-semibold">3. Refine Your App</h2>
<textarea id="refinementInput" rows="3" placeholder="Describe the changes you want to make to the app. For example: 'Add a search feature to filter tasks' or 'Change the color scheme to blue'." class="w-full p-3 text-base border border-gray-300 dark:border-gray-700 rounded-md bg-white dark:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-primary resize-y"></textarea>
<button id="refineBtn" class="w-full md:w-auto px-6 py-2 bg-primary hover:bg-primary-dark text-white font-medium rounded-md transition-colors duration-200 flex items-center justify-center">
<span id="refineBtnText">Refine App</span>
<svg id="refineBtnSpinner" class="animate-spin ml-2 h-5 w-5 text-white hidden" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
</button>
</section>
</main>
<footer class="mt-12 text-center text-gray-500 dark:text-gray-400 text-sm">
<p>Created with App Creator AI on Poe</p>
</footer>
</div>
<script>
// Dark mode detection and handling
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.documentElement.classList.add('dark');
}
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
if (event.matches) {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark');
}
});
// DOM Elements
const generateBtn = document.getElementById('generateBtn');
const generateBtnText = document.getElementById('generateBtnText');
const generateBtnSpinner = document.getElementById('generateBtnSpinner');
const appDescription = document.getElementById('appDescription');
const botSelect = document.getElementById('botSelect');
const resultsSection = document.getElementById('resultsSection');
const refinementSection = document.getElementById('refinementSection');
const codeDisplay = document.getElementById('codeDisplay');
const previewFrame = document.getElementById('previewFrame');
const copyCodeBtn = document.getElementById('copyCodeBtn');
const previewTab = document.getElementById('previewTab');
const codeTab = document.getElementById('codeTab');
const previewPanel = document.getElementById('previewPanel');
const codePanel = document.getElementById('codePanel');
const refinementInput = document.getElementById('refinementInput');
const refineBtn = document.getElementById('refineBtn');
const refineBtnText = document.getElementById('refineBtnText');
const refineBtnSpinner = document.getElementById('refineBtnSpinner');
// State variables
let currentCode = '';
// Tab switching
previewTab.addEventListener('click', () => {
previewTab.classList.add('border-b-2', 'border-primary', 'text-primary', 'dark:text-primary-light');
previewTab.classList.remove('text-gray-600', 'dark:text-gray-400');
codeTab.classList.remove('border-b-2', 'border-primary', 'text-primary', 'dark:text-primary-light');
codeTab.classList.add('text-gray-600', 'dark:text-gray-400');
previewPanel.classList.remove('hidden');
codePanel.classList.add('hidden');
});
codeTab.addEventListener('click', () => {
codeTab.classList.add('border-b-2', 'border-primary', 'text-primary', 'dark:text-primary-light');
codeTab.classList.remove('text-gray-600', 'dark:text-gray-400');
previewTab.classList.remove('border-b-2', 'border-primary', 'text-primary', 'dark:text-primary-light');
previewTab.classList.add('text-gray-600', 'dark:text-gray-400');
codePanel.classList.remove('hidden');
previewPanel.classList.add('hidden');
});
// Copy code to clipboard
copyCodeBtn.addEventListener('click', async () => {
try {
await navigator.clipboard.writeText(currentCode);
copyCodeBtn.textContent = 'Copied!';
setTimeout(() => {
copyCodeBtn.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" />
</svg>Copy Code`;
}, 2000);
} catch (err) {
console.error('Failed to copy: ', err);
}
});
// Extract code from markdown response
function extractCodeFromMarkdown(markdown) {
const codeRegex = /```(?:html|)\n([\s\S]*?)```/;
const match = markdown.match(codeRegex);
return match ? match[1] : '';
}
// Update preview iframe
function updatePreview(code) {
const blob = new Blob([code], { type: 'text/html' });
const url = URL.createObjectURL(blob);
previewFrame.src = url;
}
// Register handler for bot responses
window.Poe.registerHandler("app-creator-handler", (result, context) => {
const response = result.responses[0];
if (response.status === "error") {
setGenerating(false);
setRefining(false);
alert(`Error: ${response.statusText || 'An error occurred while generating the app'}`);
return;
}
if (response.status === "complete") {
// Extract code
const extractedCode = extractCodeFromMarkdown(response.content);
if (extractedCode) {
currentCode = extractedCode;
// Display the code with syntax highlighting
codeDisplay.textContent = currentCode;
hljs.highlightElement(codeDisplay);
// Update the preview
updatePreview(currentCode);
// Show results and refinement sections
resultsSection.classList.remove('hidden');
refinementSection.classList.remove('hidden');
} else {
alert("No code found in the response. Please try again with a more detailed description.");
}
setGenerating(false);
setRefining(false);
}
});
// Helper functions for button states
function setGenerating(isGenerating) {
if (isGenerating) {
generateBtn.disabled = true;
generateBtnText.textContent = 'Generating...';
generateBtnSpinner.classList.remove('hidden');
} else {
generateBtn.disabled = false;
generateBtnText.textContent = 'Generate App';
generateBtnSpinner.classList.add('hidden');
}
}
function setRefining(isRefining) {
if (isRefining) {
refineBtn.disabled = true;
refineBtnText.textContent = 'Refining...';
refineBtnSpinner.classList.remove('hidden');
} else {
refineBtn.disabled = false;
refineBtnText.textContent = 'Refine App';
refineBtnSpinner.classList.add('hidden');
}
}
// Generate App button handler
generateBtn.addEventListener('click', async () => {
const description = appDescription.value.trim();
if (!description) {
alert('Please enter a description of the app you want to create.');
return;
}
const selectedBot = botSelect.value;
try {
setGenerating(true);
const prompt = `@${selectedBot} Create a canvas app based on this description: "${description}".
Please provide a fully functional HTML application that can be rendered in a Poe Canvas App. Include all necessary HTML, CSS, and JavaScript in a single code block. Ensure the app is responsive and follows best practices for web development.
Your response should follow this format:
1. A brief explanation of what you've created
2. A Markdown code block containing the complete HTML/CSS/JS for the app
Make sure the code is clean, well-documented, and ready to deploy.`;
await window.Poe.sendUserMessage(prompt, {
handler: "app-creator-handler",
stream: false,
openChat: false
});
} catch (err) {
console.error('Error:', err);
alert(`Error: ${err.message || 'An error occurred while generating the app'}`);
setGenerating(false);
}
});
// Refine App button handler
refineBtn.addEventListener('click', async () => {
const refinement = refinementInput.value.trim();
if (!refinement) {
alert('Please enter a description of the changes you want to make.');
return;
}
const selectedBot = botSelect.value;
try {
setRefining(true);
const prompt = `@${selectedBot} I have a Poe Canvas App that I want to refine. Here is the current code:
\`\`\`html
${currentCode}
\`\`\`
I want to make the following changes:
"${refinement}"
Please provide an updated version of the code that implements these changes. Keep the core functionality and only modify what's necessary.
Your response should follow this format:
1. A brief explanation of what changes you've made
2. A Markdown code block containing the complete updated HTML/CSS/JS for the app`;
await window.Poe.sendUserMessage(prompt, {
handler: "app-creator-handler",
stream: false,
openChat: false
});
} catch (err) {
console.error('Error:', err);
alert(`Error: ${err.message || 'An error occurred while refining the app'}`);
setRefining(false);
}
});
</script>
</body>
</html>