// Atlas ยท Auth page โ€” Sign in / Sign up const { useState: useAuthState } = React; function GoogleLogo() { return ( ); } const TESTIMONIALS = [ { quote: "Atlas cut our technology landscaping time from three weeks to two days. The depth of the literature review is genuinely impressive.", attr: "VP of R&D, mid-cap biotech", }, { quote: "We use Atlas for every major BD decision now. The structured scope review alone saves hours of back-and-forth with analysts.", attr: "Principal, life sciences VC", }, { quote: "The citation quality matches what we'd expect from a senior researcher. It's the first AI tool our science team actually trusts.", attr: "Chief Scientific Officer, CRO", }, ]; function AuthPage() { const [tab, setTab] = useAuthState(() => { const params = new URLSearchParams(window.location.search); return params.get("mode") === "signup" ? "signup" : "signin"; }); const [testimonial] = useAuthState(() => TESTIMONIALS[Math.floor(Math.random() * TESTIMONIALS.length)]); const [step, setStep] = useAuthState("email"); // email or code const [email, setEmail] = useAuthState(""); const [code, setCode] = useAuthState(""); const [loading, setLoading] = useAuthState(false); const [error, setError] = useAuthState(""); const handleSendOtp = async (e) => { e.preventDefault(); if (!email || !email.includes("@")) { setError("Please enter a valid email address."); return; } setLoading(true); setError(""); try { const resp = await fetch("/api/auth/otp/send", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email }), }); const data = await resp.json(); if (!resp.ok) throw new Error(data.detail || "Failed to send code."); setStep("code"); } catch (err) { setError(err.message); } finally { setLoading(false); } }; const handleVerifyOtp = async (e) => { e.preventDefault(); if (code.length !== 6) { setError("Please enter the 6-digit code."); return; } setLoading(true); setError(""); try { const resp = await fetch("/api/auth/otp/verify", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email, code }), }); const data = await resp.json(); if (!resp.ok) throw new Error(data.detail || "Invalid code."); window.location.href = "/app"; } catch (err) { setError(err.message); } finally { setLoading(false); } }; return (
{/* Left panel โ€” brand + testimonial */}
Atlas
Research intelligence
for science-led teams.
{["Technology landscapes and company analyses", "Parallel AI research agents", "Literature reviews in hours, not weeks"].map((f) => (
{f}
))}
"{testimonial.quote}"
{testimonial.attr}
{/* Right panel โ€” auth form */}
{/* Atlas wordmark */}
Atlas
{/* Sign in / Sign up tabs */}
{step === "email" ? ( <> {tab === "signin" ? ( <>

Welcome back.

Sign in to your Atlas workspace to continue your reports.

) : ( <>

Create your account.

Get started with Atlas. We'll walk you through setup after you sign in.

)} {tab === "signin" ? "Continue with Google" : "Sign up with Google"}
or
setEmail(e.target.value)} placeholder="name@company.com" disabled={loading} required />
{error &&
{error}
}
) : ( <>

Check your email.

We sent a 6-digit login code to {email}.

setCode(e.target.value.replace(/\D/g, "").slice(0, 6))} placeholder="000000" pattern="\d{6}" disabled={loading} autoFocus required />
{error &&
{error}
}
)} {tab === "signin" && step === "email" && (

Don't have an account?{" "}

)} {tab === "signup" && step === "email" && (

Already have an account?{" "}

)}

By continuing you agree to Atlas's{" "} Terms of Service{" "} and{" "} Privacy Policy.

); } window.AuthPage = AuthPage;