ThinklySEO / templates /index.html
yashgori20's picture
ok
dd14242
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Thinkly Labs SEO</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background: #0a0a0a;
color: #ffffff;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
min-height: 100vh;
background-image: radial-gradient(circle at 20% 20%, rgba(120, 119, 198, 0.3) 0%, transparent 50%),
radial-gradient(circle at 80% 80%, rgba(255, 119, 198, 0.3) 0%, transparent 50%);
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 40px 20px;
}
.header {
text-align: center;
margin-bottom: 60px;
}
.logo {
font-size: 48px;
font-weight: 700;
margin-bottom: 10px;
z-index: 10;
position: relative;
display: flex;
align-items: center;
justify-content: center;
gap: 12px;
}
.logo-icon {
background: rgba(255, 255, 255, 0.1);
border-radius: 12px;
padding: 8px;
display: flex;
align-items: center;
justify-content: center;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.2);
}
.logo-svg {
width: 32px;
height: 32px;
filter: brightness(0) invert(1);
}
.logo-text {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.subtitle {
font-size: 18px;
color: #888;
margin-bottom: 40px;
}
.main-card {
background: rgba(255, 255, 255, 0.02);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 16px;
padding: 40px;
backdrop-filter: blur(10px);
margin-bottom: 40px;
}
.form-group {
margin-bottom: 24px;
}
.form-label {
display: block;
margin-bottom: 8px;
font-weight: 600;
color: #fff;
}
.form-input {
width: 100%;
padding: 16px;
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 8px;
color: #fff;
font-size: 16px;
transition: all 0.3s ease;
}
.form-input:focus {
outline: none;
border-color: #374151;
background: rgba(255, 255, 255, 0.15);
}
.form-input:not(:placeholder-shown) {
background: rgba(255, 255, 255, 0.15);
}
.form-input::placeholder {
color: #666;
}
.textarea {
min-height: 120px;
resize: vertical;
font-family: inherit;
}
.generate-btn {
width: 100%;
padding: 18px;
background: rgba(255, 255, 255, 0.1);
border: 1px solid rgba(255, 255, 255, 0.2);
border-radius: 12px;
color: white;
font-size: 18px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
margin-top: 20px;
backdrop-filter: blur(10px);
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
}
.generate-btn:hover {
transform: translateY(-2px);
background: rgba(255, 255, 255, 0.15);
border-color: rgba(255, 255, 255, 0.3);
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.4);
}
.generate-btn:disabled {
opacity: 0.6;
cursor: not-allowed;
transform: none;
}
.options-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 24px;
margin-bottom: 40px;
}
.option-card {
background: transparent;
border: none;
border-radius: 12px;
padding: 24px;
text-align: center;
cursor: default;
}
.option-icon {
font-size: 32px;
margin-bottom: 12px;
display: block;
}
.option-title {
font-size: 16px;
font-weight: 500;
margin-bottom: 6px;
color: #fff;
}
.option-desc {
color: #aaa;
font-size: 13px;
line-height: 1.4;
}
.loading-overlay {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.8);
z-index: 1000;
justify-content: center;
align-items: center;
flex-direction: column;
}
.loading-spinner {
width: 60px;
height: 60px;
border: 3px solid rgba(255, 255, 255, 0.3);
border-top: 3px solid #667eea;
border-radius: 50%;
animation: spin 1s linear infinite;
margin-bottom: 20px;
}
.loading-text {
color: #fff;
font-size: 18px;
margin-bottom: 10px;
}
.loading-subtext {
color: #888;
font-size: 14px;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.error-message {
background: rgba(220, 38, 38, 0.1);
border: 1px solid rgba(220, 38, 38, 0.3);
border-radius: 8px;
padding: 16px;
color: #fca5a5;
margin-top: 16px;
display: none;
}
@media (max-width: 768px) {
.container {
padding: 20px 16px;
}
.main-card {
padding: 24px;
}
.logo {
font-size: 36px;
}
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1 class="logo">
<span class="logo-icon">
<img src="/static/logo.svg" alt="Thinkly Logo" class="logo-svg">
</span>
<span class="logo-text">Thinkly Labs SEO</span>
</h1>
<p class="subtitle">Professional SEO Analysis & Reporting</p>
</div>
<div class="options-grid">
<div class="option-card">
<span class="option-icon">⚑</span>
<div class="option-title">Technical SEO</div>
<div class="option-desc">PageSpeed insights, Core Web Vitals</div>
</div>
<div class="option-card">
<span class="option-icon">πŸ“Š</span>
<div class="option-title">Content Audit</div>
<div class="option-desc">Metadata analysis, content quality</div>
</div>
<div class="option-card">
<span class="option-icon">πŸ†</span>
<div class="option-title">Competitor Analysis</div>
<div class="option-desc">Performance benchmarking</div>
</div>
<div class="option-card">
<span class="option-icon">πŸ“‘</span>
<div class="option-title">Professional Reports</div>
<div class="option-desc">HTML & PDF export</div>
</div>
</div>
<div class="main-card">
<form id="seoForm">
<div class="form-group">
<label class="form-label" for="url">Website URL</label>
<input type="url" id="url" name="url" class="form-input" placeholder="https://example.com" required>
</div>
<div class="form-group">
<label class="form-label" for="competitors">Competitor URLs (Optional)</label>
<textarea id="competitors" name="competitors" class="form-input textarea"
placeholder="https://competitor1.com&#10;https://competitor2.com&#10;One URL per line"></textarea>
</div>
<button type="submit" class="generate-btn" id="generateBtn">
Generate SEO Report
</button>
<div class="error-message" id="errorMessage"></div>
</form>
</div>
</div>
<div class="loading-overlay" id="loadingOverlay">
<div class="loading-spinner"></div>
<div class="loading-text" id="loadingText">Generating SEO report...</div>
<div class="loading-subtext" id="loadingSubtext">This may take a few minutes</div>
</div>
<script>
document.getElementById('seoForm').addEventListener('submit', async function (e) {
e.preventDefault();
const url = document.getElementById('url').value.trim();
const competitors = document.getElementById('competitors').value
.split('\n')
.map(c => c.trim())
.filter(c => c);
const loadingOverlay = document.getElementById('loadingOverlay');
const errorMessage = document.getElementById('errorMessage');
const loadingText = document.getElementById('loadingText');
const loadingSubtext = document.getElementById('loadingSubtext');
errorMessage.style.display = 'none';
loadingOverlay.style.display = 'flex';
const loadingMessages = [
{ text: 'Analyzing technical SEO...', subtext: 'Checking PageSpeed insights' },
{ text: 'Performing content audit...', subtext: 'Crawling website content' },
{ text: 'Analyzing competitors...', subtext: 'Comparing performance metrics' },
{ text: 'Generating professional report...', subtext: 'Creating charts and visualizations' }
];
let messageIndex = 0;
const messageInterval = setInterval(() => {
if (messageIndex < loadingMessages.length) {
loadingText.textContent = loadingMessages[messageIndex].text;
loadingSubtext.textContent = loadingMessages[messageIndex].subtext;
messageIndex++;
}
}, 3000);
try {
const response = await fetch('/generate', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
url: url,
competitors: competitors
})
});
const data = await response.json();
clearInterval(messageInterval);
loadingOverlay.style.display = 'none';
if (data.success) {
window.location.href = data.redirect_url;
} else {
errorMessage.textContent = data.error;
errorMessage.style.display = 'block';
}
} catch (error) {
clearInterval(messageInterval);
loadingOverlay.style.display = 'none';
errorMessage.textContent = 'Network error. Please try again.';
errorMessage.style.display = 'block';
}
});
</script>
</body>
</html>