-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
309 lines (283 loc) · 16.3 KB
/
index.html
File metadata and controls
309 lines (283 loc) · 16.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>OnMe - The AI Virtual Try-On for E-Commerce</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<style>
body {
font-family: 'Inter', sans-serif;
background-color: #f9fafb; /* Light Gray */
color: #111827; /* Dark Gray */
}
.gradient-text {
background: linear-gradient(to right, #4f46e5, #7c3aed);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.cta-button {
background-color: #4f46e5;
transition: background-color 0.3s ease;
}
.cta-button:hover {
background-color: #4338ca;
}
#onme-demo-modal {
background-color: rgba(0, 0, 0, 0.7);
backdrop-filter: blur(5px);
}
#onme-demo-modal .spinner {
border-top-color: #4f46e5;
animation: onme-spin 1s linear infinite;
}
@keyframes onme-spin { to { transform: rotate(360deg); } }
</style>
</head>
<body class="antialiased">
<header class="py-4 px-4 md:px-8 border-b border-gray-200 bg-white">
<nav class="container mx-auto flex justify-between items-center">
<h1 class="text-3xl font-bold text-indigo-600">OnMe</h1>
<div>
<a href="#pricing" class="text-gray-600 hover:text-indigo-600 mr-6 font-medium">Pricing</a>
<a href="https://app.onme.fit" class="cta-button text-white font-semibold py-2 px-5 rounded-lg">Client Login</a>
</div>
</nav>
</header>
<section class="text-center py-20 md:py-32 px-4 bg-white">
<div class="container mx-auto">
<h2 class="text-4xl md:text-6xl font-extrabold leading-tight text-gray-900">
Increase Conversions.<br>
<span class="gradient-text">Reduce Returns.</span>
</h2>
<p class="text-lg md:text-xl text-gray-600 mt-6 max-w-2xl mx-auto">
OnMe is the fast, reliable, and easy-to-integrate virtual try-on solution for modern e-commerce. Give your customers the confidence to click "buy".
</p>
<a href="#demo" class="cta-button text-white font-bold py-4 px-8 rounded-full inline-block mt-10 text-lg">See Live Demo</a>
</div>
</section>
<section id="demo" class="px-4 py-20 md:py-28">
<div class="container mx-auto">
<div class="bg-white border border-gray-200 rounded-2xl p-8 md:p-12 shadow-xl">
<div class="text-center mb-8">
<h3 class="text-3xl font-bold">Experience OnMe Live</h3>
<p class="text-gray-600 mt-2">Click the button below to see how the widget works on a product page.</p>
</div>
<div class="max-w-4xl mx-auto grid md:grid-cols-2 gap-8 items-center bg-gray-50 p-8 rounded-lg">
<div>
<img id="product-image-for-tryon" src="/jacket.jpg" alt="Stylish jacket" class="rounded-lg shadow-lg w-full aspect-[4/5] object-cover">
</div>
<div class="text-center md:text-left">
<h4 class="text-2xl font-bold">Premium Leather Jacket</h4>
<p class="text-3xl font-light my-2">$299.00</p>
<p class="text-gray-500 text-sm mb-6">A timeless jacket crafted from genuine leather. Perfect for any occasion.</p>
<button id="launch-demo-button" class="cta-button text-white font-semibold py-3 px-6 rounded-lg w-full md:w-auto">
✨ Virtually Try It On
</button>
</div>
</div>
</div>
</div>
</section>
<section class="py-20 md:py-28 px-4 bg-white">
<div class="container mx-auto">
<div class="text-center">
<h3 class="text-3xl md:text-4xl font-bold mb-12">Reliable Technology, Simple for Everyone.</h3>
</div>
<div class="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
<div class="bg-gray-50 p-6 rounded-lg border border-gray-200">
<h4 class="text-lg font-semibold">One-Click Setup</h4>
<p class="text-gray-600 mt-2">Integrate seamlessly with our official Shopify and WordPress apps. No coding required.</p>
</div>
<div class="bg-gray-50 p-6 rounded-lg border border-gray-200">
<h4 class="text-lg font-semibold">Blazing Fast AI</h4>
<p class="text-gray-600 mt-2">Our optimized AI pipeline delivers high-quality try-ons in seconds, keeping your customers engaged.</p>
</div>
<div class="bg-gray-50 p-6 rounded-lg border border-gray-200">
<h4 class="text-lg font-semibold">Secure & Private</h4>
<p class="text-gray-600 mt-2">We process images ephemerally and never store user photos, ensuring complete privacy and trust.</p>
</div>
</div>
</div>
</section>
<section id="pricing" class="py-20 md:py-28 px-4">
<div class="container mx-auto">
<div class="text-center">
<h3 class="text-3xl md:text-4xl font-bold mb-12">Simple, Transparent Pricing</h3>
</div>
<div class="flex flex-col md:flex-row justify-center items-center gap-8">
<div class="bg-white border-2 border-indigo-500 w-full max-w-sm p-8 rounded-lg shadow-2xl">
<h4 class="text-xl font-semibold">Pro Plan</h4>
<p class="text-4xl font-bold my-4">$49<span class="text-base font-medium text-gray-500">/mo</span></p>
<ul class="space-y-3 text-gray-600 mb-6">
<li><span class="text-indigo-500 mr-2">✓</span> AI Virtual Try-On Widget</li>
<li><span class="text-indigo-500 mr-2">✓</span> Up to 5,000 try-ons/mo</li>
<li><span class="text-indigo-500 mr-2">✓</span> Analytics Dashboard</li>
</ul>
<a href="https://app.onme.fit" class="cta-button w-full block text-center text-white font-semibold py-3 px-4 rounded-md">Get Started</a>
</div>
<div class="bg-white border border-gray-200 w-full max-w-sm p-8 rounded-lg">
<h4 class="text-xl font-semibold">Enterprise</h4>
<p class="text-4xl font-bold my-4">Custom</p>
<ul class="space-y-3 text-gray-600 mb-6">
<li><span class="text-indigo-500 mr-2">✓</span> Unlimited Try-Ons</li>
<li><span class="text-indigo-500 mr-2">✓</span> Dedicated Support & Onboarding</li>
<li><span class="text-indigo-500 mr-2">✓</span> Custom Integrations</li>
</ul>
<a href="mailto:sales@onme.fit" class="w-full mt-auto block text-center border-2 border-gray-300 text-gray-800 font-semibold py-3 px-4 rounded-md hover:bg-gray-100 transition-colors">Contact Sales</a>
</div>
</div>
</div>
</section>
<footer class="border-t border-gray-200 mt-20 bg-white">
<div class="container mx-auto py-8 px-4 text-center text-gray-500">
<p>© 2025 OnMe. All rights reserved.</p>
<div class="mt-4 text-sm">
<a href="#" class="hover:text-gray-800">Terms of Service</a>
<span class="mx-2">|</span>
<a href="#" class="hover:text-gray-800">Privacy Policy</a>
</div>
</div>
</footer>
<div id="onme-demo-modal" class="fixed inset-0 z-50 hidden items-center justify-center p-4">
<div class="bg-white text-gray-800 rounded-2xl shadow-xl p-6 w-full max-w-md max-h-full overflow-y-auto relative">
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
const launchButton = document.getElementById('launch-demo-button');
const demoModal = document.getElementById('onme-demo-modal');
const modalContent = demoModal.querySelector('div');
let personImageBase64 = null;
let clothingImageBase64 = null;
function openModal() {
if (!clothingImageBase64) {
alert("Demo product image is still loading. Please try again in a moment.");
return;
}
modalContent.innerHTML = getWidgetHTML();
demoModal.classList.remove('hidden');
demoModal.classList.add('flex');
attachWidgetListeners();
}
function closeModal() {
demoModal.classList.add('hidden');
demoModal.classList.remove('flex');
modalContent.innerHTML = '';
}
function getWidgetHTML() {
return `
<button id="onme-modal-close-button" class="absolute top-4 right-4 text-gray-400 hover:text-gray-600 text-3xl z-10">×</button>
<div id="main-widget-view">
<h3 class="text-xl font-bold text-center mb-1">Virtual Try-On</h3>
<p class="text-sm text-gray-500 text-center mb-4">Upload your photo to see this on you!</p>
<div class="text-center mb-4">
<img id="onme-person-preview" src="https://placehold.co/300x400/EFEFEF/333333?text=Your+Photo" alt="User photo preview" class="w-full max-w-[200px] mx-auto aspect-[3/4] object-cover rounded-lg bg-gray-100 shadow-inner">
<label for="onme-person-upload" id="onme-upload-label" class="cursor-pointer text-sm font-semibold text-indigo-600 hover:text-indigo-800 mt-2 inline-block">Upload Your Photo</label>
<input type="file" id="onme-person-upload" class="hidden" accept="image/*">
</div>
<div class="text-xs text-gray-500 text-center my-2 px-4">
<input type="checkbox" id="age-confirm" class="mr-1">
<label for="age-confirm">I confirm I am 18 or older and agree to the <a href="#" class="underline">Terms of Service</a>.</label>
</div>
<div class="flex flex-col items-center">
<button id="onme-generate-button" class="w-full text-center bg-indigo-600 text-white font-semibold py-2.5 px-4 rounded-lg hover:bg-indigo-700 transition-colors shadow-sm disabled:bg-indigo-300" disabled>Generate Try-On</button>
<div id="onme-loading-spinner" class="spinner w-8 h-8 rounded-full border-4 border-gray-300 hidden my-2"></div>
<p id="onme-message" class="text-xs text-gray-500 mt-2 h-auto text-center"></p>
</div>
</div>
`;
}
function attachWidgetListeners() {
const ageConfirmCheckbox = document.getElementById('age-confirm');
const generateButton = document.getElementById('onme-generate-button');
document.getElementById('onme-modal-close-button').onclick = closeModal;
demoModal.onclick = (e) => { if (e.target === demoModal) closeModal(); };
ageConfirmCheckbox.onchange = () => {
generateButton.disabled = !ageConfirmCheckbox.checked || !personImageBase64;
};
document.getElementById('onme-person-upload').onchange = async (event) => {
const file = event.target.files[0];
if (!file) return;
document.getElementById('onme-person-preview').src = URL.createObjectURL(file);
document.getElementById('onme-upload-label').textContent = 'Change Photo';
personImageBase64 = await fileToBase64(file);
generateButton.disabled = !ageConfirmCheckbox.checked;
};
generateButton.onclick = handleGeneration;
}
async function handleGeneration() {
updateUIState(true, 'Generating your try-on...');
try {
const API_URL = `/api/generate-tryon`;
const response = await fetch(API_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
personImage: personImageBase64,
clothingImage: clothingImageBase64
}),
});
if (!response.ok) {
const errorResult = await response.json();
throw new Error(errorResult.error || 'The AI model failed to generate an image.');
}
const result = await response.json();
const imageUrl = `data:image/jpeg;base64,${result.generatedImage}`;
showResult(imageUrl);
} catch (error) {
console.error("API Error:", error);
updateUIState(false, `Error: ${error.message}`);
}
}
function showResult(imageUrl) {
updateUIState(false);
modalContent.innerHTML = `
<button id="onme-modal-close-button" class="absolute top-4 right-4 text-gray-400 hover:text-gray-600 text-3xl z-10">×</button>
<h3 class="text-xl font-bold text-center mb-4">Here's Your Try-On!</h3>
<img src="${imageUrl}" alt="Generated try-on image" class="w-full max-w-sm mx-auto aspect-[3/4] object-contain rounded-lg bg-gray-100">
<div class="text-center mt-6">
<a href="https://app.onme.fit" class="cta-button text-white font-bold py-3 px-8 rounded-full hover:bg-indigo-700 text-lg shadow-lg">Get OnMe for Your Store</a>
</div>
`;
document.getElementById('onme-modal-close-button').onclick = closeModal;
}
const fileToBase64 = file => new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result.split(',')[1]);
reader.onerror = error => reject(error);
});
const urlToBase64 = async (url) => {
const response = await fetch(url);
const blob = await response.blob();
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onloadend = () => resolve(reader.result.split(',')[1]);
reader.onerror = reject;
reader.readAsDataURL(blob);
});
};
const updateUIState = (isLoading = false, message = '') => {
const spinner = document.getElementById('onme-loading-spinner');
const button = document.getElementById('onme-generate-button');
const msgElement = document.getElementById('onme-message');
if (spinner) spinner.classList.toggle('hidden', !isLoading);
if (button) button.classList.toggle('hidden', isLoading);
if (msgElement) msgElement.textContent = message;
};
const initProductImage = async () => {
try {
clothingImageBase64 = await urlToBase64('/jacket.jpg');
console.log('Product image loaded successfully.');
} catch (error) {
console.error('Failed to load product image:', error);
}
};
initProductImage();
launchButton.addEventListener('click', openModal);
});
</script>
</body>
</html>