diff --git a/public/app.js b/public/app.js index 2094fc8..6a04382 100644 --- a/public/app.js +++ b/public/app.js @@ -2,9 +2,9 @@ function openSignup() { document.getElementById('signupModal').classList.add('active'); document.getElementById('signupForm').style.display = 'block'; document.getElementById('keyResult').style.display = 'none'; - document.getElementById('signupEmail').value = ''; document.getElementById('signupError').style.display = 'none'; - setTimeout(function() { document.getElementById('signupEmail').focus(); }, 100); + document.getElementById('signupBtn').textContent = 'Get API Key'; + document.getElementById('signupBtn').disabled = false; } function closeSignup() { @@ -16,35 +16,33 @@ document.getElementById('signupModal').addEventListener('click', function(e) { if (e.target === this) closeSignup(); }); -// Submit on Enter -document.getElementById('signupEmail').addEventListener('keydown', function(e) { - if (e.key === 'Enter') submitSignup(); -}); - async function submitSignup() { - var email = document.getElementById('signupEmail').value.trim(); var errEl = document.getElementById('signupError'); var btn = document.getElementById('signupBtn'); - if (!email) { - errEl.textContent = 'Please enter your email.'; - errEl.style.display = 'block'; - return; - } - btn.textContent = 'Creating...'; btn.disabled = true; + errEl.style.display = 'none'; try { var res = await fetch('/v1/signup/free', { method: 'POST', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ email: email }) + body: JSON.stringify({}) }); + + if (res.status === 429) { + errEl.textContent = 'Too many requests. Please try again in a few minutes.'; + errEl.style.display = 'block'; + btn.textContent = 'Get API Key'; + btn.disabled = false; + return; + } + var data = await res.json(); if (!res.ok) { - errEl.textContent = data.error || 'Something went wrong.'; + errEl.textContent = data.error || 'Something went wrong. Please try again.'; errEl.style.display = 'block'; btn.textContent = 'Get API Key'; btn.disabled = false; @@ -72,7 +70,6 @@ function copyKey() { } try { navigator.clipboard.writeText(key).then(showCopied).catch(function() { - // Fallback for older browsers / non-secure contexts var ta = document.createElement('textarea'); ta.value = key; ta.style.position = 'fixed'; ta.style.opacity = '0'; document.body.appendChild(ta); ta.select(); diff --git a/public/index.html b/public/index.html index b93fb9a..bc3c9e3 100644 --- a/public/index.html +++ b/public/index.html @@ -223,17 +223,17 @@ footer { padding: 40px 0; text-align: center; color: var(--muted); font-size: 0.

Get Your Free API Key

-

Enter your email and get an API key instantly. No credit card required.

+

One click. No email, no credit card.

-

🚀 You're in!

-

Here's your API key. Save it now — it won't be shown again.

+

Here's your API key:

Click to copy
-

100 free PDFs/month • All endpoints • View docs →

+

⚠️ Save your API key — we can't recover it later.

+

100 free PDFs/month • All endpoints • View docs →

diff --git a/src/routes/signup.ts b/src/routes/signup.ts index 201f547..f98c1ab 100644 --- a/src/routes/signup.ts +++ b/src/routes/signup.ts @@ -20,20 +20,19 @@ const signupLimiter = rateLimit({ // Self-service free API key signup router.post("/free", signupLimiter, (req: Request, res: Response) => { - const { email } = req.body; + const { email } = req.body || {}; - if (!email || typeof email !== "string") { - res.status(400).json({ error: "Email is required" }); - return; + // Email is optional — validate only if provided + let cleanEmail: string | undefined; + if (email && typeof email === "string") { + if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) { + res.status(400).json({ error: "Invalid email address" }); + return; + } + cleanEmail = email.trim().toLowerCase(); } - // Basic email validation - if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) { - res.status(400).json({ error: "Invalid email address" }); - return; - } - - const keyInfo = createFreeKey(email.trim().toLowerCase()); + const keyInfo = createFreeKey(cleanEmail); res.json({ message: "Welcome to DocFast! 🚀", diff --git a/src/services/keys.ts b/src/services/keys.ts index 5601c7b..228efd5 100644 --- a/src/services/keys.ts +++ b/src/services/keys.ts @@ -67,15 +67,17 @@ function generateKey(prefix: string): string { return `${prefix}_${randomBytes(24).toString("hex")}`; } -export function createFreeKey(email: string): ApiKey { - // Check if email already has a free key - const existing = store.keys.find((k) => k.email === email && k.tier === "free"); - if (existing) return existing; +export function createFreeKey(email?: string): ApiKey { + // If email provided, check if it already has a free key + if (email) { + const existing = store.keys.find((k) => k.email === email && k.tier === "free"); + if (existing) return existing; + } const entry: ApiKey = { key: generateKey("df_free"), tier: "free", - email, + email: email || "", createdAt: new Date().toISOString(), }; store.keys.push(entry);