ai_image_generation / index.html
nerala's picture
Build a Shopify app that is retrieving images from the shop account and generates product / marketing videos using an LLM for video generation. - Initial Deployment
6e1e935 verified
Raw
History Blame Contribute Delete
32.1 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Shopify VideoGen - AI Marketing Video Generator</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
.animate-pulse {
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
.gradient-bg {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.video-preview {
aspect-ratio: 16/9;
}
.scrollbar-hide::-webkit-scrollbar {
display: none;
}
</style>
</head>
<body class="bg-gray-50 font-sans">
<div class="min-h-screen flex flex-col">
<!-- Header -->
<header class="gradient-bg text-white shadow-lg">
<div class="container mx-auto px-4 py-6">
<div class="flex justify-between items-center">
<div class="flex items-center space-x-2">
<i class="fas fa-video text-2xl"></i>
<h1 class="text-2xl font-bold">Shopify VideoGen</h1>
</div>
<div class="flex items-center space-x-4">
<button id="connectShopify" class="bg-white text-indigo-700 px-4 py-2 rounded-lg font-medium hover:bg-gray-100 transition">
<i class="fas fa-store mr-2"></i>Connect Shopify
</button>
<div class="relative">
<img src="https://randomuser.me/api/portraits/women/44.jpg" alt="Profile" class="w-10 h-10 rounded-full cursor-pointer border-2 border-white">
<div class="absolute bottom-0 right-0 bg-green-500 rounded-full w-3 h-3 border-2 border-white"></div>
</div>
</div>
</div>
</div>
</header>
<!-- Main Content -->
<main class="flex-grow container mx-auto px-4 py-8">
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
<!-- Left Sidebar - Products -->
<div class="lg:col-span-1 bg-white rounded-xl shadow-md overflow-hidden">
<div class="p-6 border-b border-gray-200">
<h2 class="text-xl font-semibold text-gray-800 flex items-center">
<i class="fas fa-box-open mr-2 text-indigo-600"></i> Your Products
</h2>
<div class="mt-4 relative">
<input type="text" placeholder="Search products..." class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500">
<i class="fas fa-search absolute right-3 top-3 text-gray-400"></i>
</div>
</div>
<div class="overflow-y-auto h-96 scrollbar-hide">
<!-- Product List -->
<div class="divide-y divide-gray-200">
<!-- Product Item 1 -->
<div class="p-4 hover:bg-gray-50 cursor-pointer transition product-item" data-product-id="1">
<div class="flex items-start space-x-3">
<img src="https://cdn.shopify.com/s/files/1/0533/2089/files/placeholder-images-product-1_large.png?v=1530129292" alt="Product 1" class="w-16 h-16 object-cover rounded-lg">
<div>
<h3 class="font-medium text-gray-900">Premium Leather Wallet</h3>
<p class="text-sm text-gray-500">5 images available</p>
<div class="flex mt-1">
<span class="bg-green-100 text-green-800 text-xs px-2 py-1 rounded">In stock</span>
</div>
</div>
</div>
</div>
<!-- Product Item 2 -->
<div class="p-4 hover:bg-gray-50 cursor-pointer transition product-item" data-product-id="2">
<div class="flex items-start space-x-3">
<img src="https://cdn.shopify.com/s/files/1/0533/2089/files/placeholder-images-product-2_large.png?v=1530129292" alt="Product 2" class="w-16 h-16 object-cover rounded-lg">
<div>
<h3 class="font-medium text-gray-900">Wireless Headphones</h3>
<p class="text-sm text-gray-500">8 images available</p>
<div class="flex mt-1">
<span class="bg-green-100 text-green-800 text-xs px-2 py-1 rounded">In stock</span>
</div>
</div>
</div>
</div>
<!-- Product Item 3 -->
<div class="p-4 hover:bg-gray-50 cursor-pointer transition product-item" data-product-id="3">
<div class="flex items-start space-x-3">
<img src="https://cdn.shopify.com/s/files/1/0533/2089/files/placeholder-images-product-3_large.png?v=1530129292" alt="Product 3" class="w-16 h-16 object-cover rounded-lg">
<div>
<h3 class="font-medium text-gray-900">Organic Cotton T-Shirt</h3>
<p class="text-sm text-gray-500">4 images available</p>
<div class="flex mt-1">
<span class="bg-yellow-100 text-yellow-800 text-xs px-2 py-1 rounded">Low stock</span>
</div>
</div>
</div>
</div>
<!-- Product Item 4 -->
<div class="p-4 hover:bg-gray-50 cursor-pointer transition product-item" data-product-id="4">
<div class="flex items-start space-x-3">
<img src="https://cdn.shopify.com/s/files/1/0533/2089/files/placeholder-images-product-4_large.png?v=1530129292" alt="Product 4" class="w-16 h-16 object-cover rounded-lg">
<div>
<h3 class="font-medium text-gray-900">Stainless Steel Water Bottle</h3>
<p class="text-sm text-gray-500">6 images available</p>
<div class="flex mt-1">
<span class="bg-green-100 text-green-800 text-xs px-2 py-1 rounded">In stock</span>
</div>
</div>
</div>
</div>
<!-- Product Item 5 -->
<div class="p-4 hover:bg-gray-50 cursor-pointer transition product-item" data-product-id="5">
<div class="flex items-start space-x-3">
<img src="https://cdn.shopify.com/s/files/1/0533/2089/files/placeholder-images-product-5_large.png?v=1530129292" alt="Product 5" class="w-16 h-16 object-cover rounded-lg">
<div>
<h3 class="font-medium text-gray-900">Smart Watch Pro</h3>
<p class="text-sm text-gray-500">7 images available</p>
<div class="flex mt-1">
<span class="bg-red-100 text-red-800 text-xs px-2 py-1 rounded">Out of stock</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Main Content Area -->
<div class="lg:col-span-2 space-y-6">
<!-- Selected Product Display -->
<div class="bg-white rounded-xl shadow-md overflow-hidden">
<div class="p-6 border-b border-gray-200">
<h2 class="text-xl font-semibold text-gray-800 flex items-center">
<i class="fas fa-cube mr-2 text-indigo-600"></i> Selected Product
</h2>
<div id="selectedProduct" class="mt-4 text-center py-8 text-gray-400">
<i class="fas fa-box-open text-4xl mb-2"></i>
<p>Select a product from the left to get started</p>
</div>
<div id="productDetails" class="hidden">
<div class="flex flex-col md:flex-row gap-6">
<div class="md:w-1/3">
<img id="productMainImage" src="" alt="Product" class="w-full rounded-lg shadow-sm border border-gray-200">
</div>
<div class="md:w-2/3">
<h3 id="productTitle" class="text-2xl font-bold text-gray-900"></h3>
<p id="productDescription" class="mt-2 text-gray-600"></p>
<div class="mt-4 flex flex-wrap gap-2">
<span id="productPrice" class="bg-blue-100 text-blue-800 px-3 py-1 rounded-full text-sm font-medium"></span>
<span id="productStock" class="bg-green-100 text-green-800 px-3 py-1 rounded-full text-sm font-medium"></span>
<span id="productType" class="bg-purple-100 text-purple-800 px-3 py-1 rounded-full text-sm font-medium"></span>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Product Images -->
<div id="productImagesSection" class="bg-white rounded-xl shadow-md overflow-hidden hidden">
<div class="p-6 border-b border-gray-200">
<h2 class="text-xl font-semibold text-gray-800 flex items-center">
<i class="fas fa-images mr-2 text-indigo-600"></i> Available Images
</h2>
<p class="mt-1 text-sm text-gray-500">Select images to include in your video</p>
<div class="mt-4 grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-4" id="productImagesContainer">
<!-- Images will be loaded here -->
</div>
</div>
</div>
<!-- Video Generation Settings -->
<div id="videoSettings" class="bg-white rounded-xl shadow-md overflow-hidden hidden">
<div class="p-6 border-b border-gray-200">
<h2 class="text-xl font-semibold text-gray-800 flex items-center">
<i class="fas fa-sliders-h mr-2 text-indigo-600"></i> Video Settings
</h2>
<div class="mt-6 grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Video Style</label>
<select class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-indigo-500 focus:border-indigo-500">
<option>Product Showcase</option>
<option>Lifestyle</option>
<option>Testimonial</option>
<option>How-To</option>
<option>Promotional</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Video Length</label>
<select class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-indigo-500 focus:border-indigo-500">
<option>15 seconds</option>
<option>30 seconds</option>
<option>45 seconds</option>
<option>60 seconds</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Music</label>
<select class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-indigo-500 focus:border-indigo-500">
<option>Upbeat</option>
<option>Calm</option>
<option>Corporate</option>
<option>Trendy</option>
<option>No music</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Voiceover</label>
<select class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-indigo-500 focus:border-indigo-500">
<option>Male Voice</option>
<option>Female Voice</option>
<option>No voiceover</option>
</select>
</div>
</div>
<div class="mt-6">
<label class="block text-sm font-medium text-gray-700 mb-1">Custom Script (optional)</label>
<textarea class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-indigo-500 focus:border-indigo-500" rows="3" placeholder="Enter custom script for your video..."></textarea>
</div>
<div class="mt-6">
<label class="block text-sm font-medium text-gray-700 mb-1">Call to Action</label>
<div class="grid grid-cols-2 sm:grid-cols-4 gap-2">
<button class="px-3 py-2 border border-gray-300 rounded-lg hover:bg-gray-50">Shop Now</button>
<button class="px-3 py-2 border border-gray-300 rounded-lg hover:bg-gray-50">Learn More</button>
<button class="px-3 py-2 border border-gray-300 rounded-lg hover:bg-gray-50">Subscribe</button>
<button class="px-3 py-2 border border-gray-300 rounded-lg hover:bg-gray-50">Custom...</button>
</div>
</div>
</div>
</div>
<!-- Video Preview -->
<div id="videoPreviewSection" class="bg-white rounded-xl shadow-md overflow-hidden hidden">
<div class="p-6 border-b border-gray-200">
<h2 class="text-xl font-semibold text-gray-800 flex items-center">
<i class="fas fa-play-circle mr-2 text-indigo-600"></i> Video Preview
</h2>
<p class="mt-1 text-sm text-gray-500">Your AI-generated marketing video</p>
<div class="mt-6">
<div class="video-preview bg-black rounded-lg overflow-hidden flex items-center justify-center relative">
<div id="videoPlaceholder" class="text-white text-center p-6">
<i class="fas fa-video text-4xl mb-3"></i>
<p>Generate your video to see the preview</p>
</div>
<video id="generatedVideo" class="w-full h-full hidden" controls></video>
</div>
<div class="mt-4 flex flex-col sm:flex-row justify-between items-center gap-4">
<div class="flex items-center">
<span class="text-sm text-gray-500 mr-2">Status:</span>
<span id="videoStatus" class="px-2 py-1 rounded-full text-xs font-medium bg-gray-100 text-gray-800">Not generated</span>
</div>
<div class="flex space-x-2">
<button id="generateBtn" class="gradient-bg text-white px-6 py-2 rounded-lg font-medium hover:opacity-90 transition flex items-center">
<i class="fas fa-magic mr-2"></i> Generate Video
</button>
<button id="downloadBtn" class="bg-gray-200 text-gray-800 px-6 py-2 rounded-lg font-medium hover:bg-gray-300 transition flex items-center hidden">
<i class="fas fa-download mr-2"></i> Download
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
<!-- Footer -->
<footer class="bg-gray-800 text-white py-6">
<div class="container mx-auto px-4">
<div class="flex flex-col md:flex-row justify-between items-center">
<div class="mb-4 md:mb-0">
<div class="flex items-center space-x-2">
<i class="fas fa-video text-xl"></i>
<span class="text-xl font-bold">Shopify VideoGen</span>
</div>
<p class="text-gray-400 text-sm mt-1">AI-powered marketing videos for your Shopify store</p>
</div>
<div class="flex space-x-6">
<a href="#" class="text-gray-300 hover:text-white transition"><i class="fab fa-facebook-f"></i></a>
<a href="#" class="text-gray-300 hover:text-white transition"><i class="fab fa-twitter"></i></a>
<a href="#" class="text-gray-300 hover:text-white transition"><i class="fab fa-instagram"></i></a>
<a href="#" class="text-gray-300 hover:text-white transition"><i class="fab fa-linkedin-in"></i></a>
</div>
</div>
<div class="border-t border-gray-700 mt-6 pt-6 text-sm text-gray-400 text-center">
<p>© 2023 Shopify VideoGen. All rights reserved.</p>
</div>
</div>
</footer>
</div>
<!-- Loading Modal -->
<div id="loadingModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden">
<div class="bg-white rounded-xl p-8 max-w-md w-full mx-4">
<div class="text-center">
<div class="animate-spin rounded-full h-16 w-16 border-t-4 border-b-4 border-indigo-500 mx-auto mb-4"></div>
<h3 class="text-xl font-semibold text-gray-900 mb-2">Generating Your Video</h3>
<p class="text-gray-600 mb-4">Our AI is creating a stunning marketing video for your product. This may take a few moments.</p>
<div class="w-full bg-gray-200 rounded-full h-2.5">
<div id="progressBar" class="gradient-bg h-2.5 rounded-full" style="width: 0%"></div>
</div>
<p id="progressText" class="text-sm text-gray-500 mt-2">Initializing...</p>
</div>
</div>
</div>
<script>
// Sample product data
const products = {
1: {
title: "Premium Leather Wallet",
description: "Handcrafted from full-grain leather, this wallet combines durability with timeless style. Features multiple card slots and a cash compartment.",
price: "$49.99",
stock: "In stock",
type: "Accessories",
images: [
"https://cdn.shopify.com/s/files/1/0533/2089/files/placeholder-images-product-1_large.png?v=1530129292",
"https://cdn.shopify.com/s/files/1/0533/2089/files/placeholder-images-product-2_large.png?v=1530129292",
"https://cdn.shopify.com/s/files/1/0533/2089/files/placeholder-images-product-3_large.png?v=1530129292",
"https://cdn.shopify.com/s/files/1/0533/2089/files/placeholder-images-product-4_large.png?v=1530129292",
"https://cdn.shopify.com/s/files/1/0533/2089/files/placeholder-images-product-5_large.png?v=1530129292"
]
},
2: {
title: "Wireless Headphones",
description: "Premium noise-cancelling wireless headphones with 30-hour battery life. Crystal clear sound and comfortable over-ear design.",
price: "$199.99",
stock: "In stock",
type: "Electronics",
images: [
"https://cdn.shopify.com/s/files/1/0533/2089/files/placeholder-images-product-2_large.png?v=1530129292",
"https://cdn.shopify.com/s/files/1/0533/2089/files/placeholder-images-product-1_large.png?v=1530129292",
"https://cdn.shopify.com/s/files/1/0533/2089/files/placeholder-images-product-4_large.png?v=1530129292",
"https://cdn.shopify.com/s/files/1/0533/2089/files/placeholder-images-product-5_large.png?v=1530129292"
]
},
3: {
title: "Organic Cotton T-Shirt",
description: "100% organic cotton t-shirt, ethically made. Soft, breathable fabric with a classic fit. Available in multiple colors.",
price: "$29.99",
stock: "Low stock",
type: "Apparel",
images: [
"https://cdn.shopify.com/s/files/1/0533/2089/files/placeholder-images-product-3_large.png?v=1530129292",
"https://cdn.shopify.com/s/files/1/0533/2089/files/placeholder-images-product-1_large.png?v=1530129292",
"https://cdn.shopify.com/s/files/1/0533/2089/files/placeholder-images-product-5_large.png?v=1530129292"
]
}
};
// DOM elements
const productItems = document.querySelectorAll('.product-item');
const selectedProduct = document.getElementById('selectedProduct');
const productDetails = document.getElementById('productDetails');
const productImagesSection = document.getElementById('productImagesSection');
const productImagesContainer = document.getElementById('productImagesContainer');
const videoSettings = document.getElementById('videoSettings');
const videoPreviewSection = document.getElementById('videoPreviewSection');
const generateBtn = document.getElementById('generateBtn');
const downloadBtn = document.getElementById('downloadBtn');
const loadingModal = document.getElementById('loadingModal');
const progressBar = document.getElementById('progressBar');
const progressText = document.getElementById('progressText');
const videoPlaceholder = document.getElementById('videoPlaceholder');
const generatedVideo = document.getElementById('generatedVideo');
const videoStatus = document.getElementById('videoStatus');
const connectShopifyBtn = document.getElementById('connectShopify');
// Product selection
productItems.forEach(item => {
item.addEventListener('click', function() {
const productId = this.getAttribute('data-product-id');
loadProductDetails(productId);
});
});
// Load product details
function loadProductDetails(productId) {
const product = products[productId];
if (product) {
// Hide placeholder, show details
selectedProduct.classList.add('hidden');
productDetails.classList.remove('hidden');
// Update product details
document.getElementById('productTitle').textContent = product.title;
document.getElementById('productDescription').textContent = product.description;
document.getElementById('productPrice').textContent = product.price;
document.getElementById('productStock').textContent = product.stock;
document.getElementById('productType').textContent = product.type;
document.getElementById('productMainImage').src = product.images[0];
// Load product images
loadProductImages(product.images);
// Show sections
productImagesSection.classList.remove('hidden');
videoSettings.classList.remove('hidden');
videoPreviewSection.classList.remove('hidden');
// Reset video section
videoPlaceholder.classList.remove('hidden');
generatedVideo.classList.add('hidden');
downloadBtn.classList.add('hidden');
videoStatus.textContent = "Not generated";
videoStatus.className = "px-2 py-1 rounded-full text-xs font-medium bg-gray-100 text-gray-800";
}
}
// Load product images
function loadProductImages(images) {
productImagesContainer.innerHTML = '';
images.forEach((image, index) => {
const imgContainer = document.createElement('div');
imgContainer.className = 'relative cursor-pointer group';
imgContainer.innerHTML = `
<img src="${image}" alt="Product image ${index + 1}" class="w-full h-32 object-cover rounded-lg border-2 border-transparent group-hover:border-indigo-500 transition">
<div class="absolute inset-0 bg-black bg-opacity-0 group-hover:bg-opacity-20 rounded-lg transition flex items-center justify-center">
<i class="fas fa-check-circle text-white text-2xl opacity-0 group-hover:opacity-100 transition"></i>
</div>
`;
productImagesContainer.appendChild(imgContainer);
});
}
// Generate video
generateBtn.addEventListener('click', function() {
// Show loading modal
loadingModal.classList.remove('hidden');
// Simulate video generation progress
let progress = 0;
const interval = setInterval(() => {
progress += Math.random() * 10;
if (progress > 100) progress = 100;
progressBar.style.width = `${progress}%`;
if (progress < 30) {
progressText.textContent = "Analyzing product images...";
} else if (progress < 60) {
progressText.textContent = "Generating video script with AI...";
} else if (progress < 90) {
progressText.textContent = "Rendering video...";
} else {
progressText.textContent = "Finalizing your video...";
}
if (progress === 100) {
clearInterval(interval);
setTimeout(() => {
loadingModal.classList.add('hidden');
// Show generated video
videoPlaceholder.classList.add('hidden');
generatedVideo.classList.remove('hidden');
generatedVideo.src = "https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4"; // Sample video
// Update status
videoStatus.textContent = "Ready";
videoStatus.className = "px-2 py-1 rounded-full text-xs font-medium bg-green-100 text-green-800";
// Show download button
downloadBtn.classList.remove('hidden');
}, 1000);
}
}, 300);
});
// Download video
downloadBtn.addEventListener('click', function() {
// In a real app, this would trigger a download
alert('Video download started!');
});
// Connect Shopify button
connectShopifyBtn.addEventListener('click', function() {
// In a real app, this would open Shopify OAuth flow
alert('Redirecting to Shopify for authentication...');
});
// Sample video generation (for demo purposes)
function simulateVideoGeneration() {
console.log("Video generation process started with LLM...");
// This would be replaced with actual API calls to your video generation service
}
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=nerala/ai-video-generation" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>