feat: email verification for free tier signup
- Signup now requires email verification before API key is revealed - Verification token sent via email (Resend) with console fallback - GET /verify?token=xxx shows API key in styled HTML page - Handles expired (24h), invalid, and already-verified tokens - Frontend modal shows 'check your email' instead of key - Keeps existing rate limiting
This commit is contained in:
parent
890b82e5ec
commit
1b20665b0d
7 changed files with 252 additions and 29 deletions
|
|
@ -9,6 +9,7 @@ function openSignup() {
|
|||
document.getElementById('signupModal').classList.add('active');
|
||||
showState('signupInitial');
|
||||
document.getElementById('signupError').style.display = 'none';
|
||||
document.getElementById('signupEmail').value = '';
|
||||
}
|
||||
|
||||
function closeSignup() {
|
||||
|
|
@ -18,6 +19,15 @@ function closeSignup() {
|
|||
async function submitSignup() {
|
||||
var errEl = document.getElementById('signupError');
|
||||
var btn = document.getElementById('signupBtn');
|
||||
var emailInput = document.getElementById('signupEmail');
|
||||
var email = emailInput.value.trim();
|
||||
|
||||
if (!email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
|
||||
errEl.textContent = 'Please enter a valid email address.';
|
||||
errEl.style.display = 'block';
|
||||
return;
|
||||
}
|
||||
|
||||
errEl.style.display = 'none';
|
||||
btn.disabled = true;
|
||||
showState('signupLoading');
|
||||
|
|
@ -26,7 +36,7 @@ async function submitSignup() {
|
|||
var res = await fetch('/v1/signup/free', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({})
|
||||
body: JSON.stringify({ email: email })
|
||||
});
|
||||
var data = await res.json();
|
||||
|
||||
|
|
@ -38,7 +48,7 @@ async function submitSignup() {
|
|||
return;
|
||||
}
|
||||
|
||||
document.getElementById('apiKeyText').textContent = data.apiKey;
|
||||
// Show "check your email" message
|
||||
showState('signupResult');
|
||||
} catch (err) {
|
||||
showState('signupInitial');
|
||||
|
|
@ -86,11 +96,9 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
document.getElementById('btn-checkout').addEventListener('click', checkout);
|
||||
document.getElementById('btn-close-signup').addEventListener('click', closeSignup);
|
||||
document.getElementById('signupBtn').addEventListener('click', submitSignup);
|
||||
document.getElementById('copyBtn').addEventListener('click', copyKey);
|
||||
document.getElementById('signupModal').addEventListener('click', function(e) {
|
||||
if (e.target === this) closeSignup();
|
||||
});
|
||||
// Smooth scroll for nav links
|
||||
document.querySelectorAll('a[href^="#"]').forEach(function(a) {
|
||||
a.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue