import { useAuth } from '../contexts/AuthContext' import { useNavigate } from 'react-router-dom' import { useEffect, useState } from 'react' import { GoogleSignInButton } from '../components/GoogleSignInButton' import { TreeAnimation } from '../components/TreeAnimation' import { PageLoader } from '../components/PageLoader' import { usePageMeta } from '../hooks/usePageMeta' export default function LoginPage() { usePageMeta({ title: 'Private Gratitude Journal App | Grateful Journal', description: 'A private, end-to-end encrypted gratitude journal. No feeds, no noise — just you and your thoughts. Grow your gratitude one moment at a time.', canonical: 'https://gratefuljournal.online/', }) const { user, loading, signInWithGoogle, authError } = useAuth() const navigate = useNavigate() const [signingIn, setSigningIn] = useState(false) const [error, setError] = useState(null) useEffect(() => { if (loading) return if (user) navigate('/write', { replace: true }) }, [user, loading, navigate]) async function handleGoogleSignIn() { setError(null) setSigningIn(true) try { await signInWithGoogle() } catch (e) { setError(e instanceof Error ? e.message : 'Sign-in failed') } finally { setSigningIn(false) } } // Keep showing the loader until the navigate effect fires. // Without the `user` check here, the login form flashes for one frame // between loading→false and the useEffect redirect. if (loading || signingIn || user) { return } return (
{/* ── Left: animated tree hero ─────────────────── */}

Grow your gratitude.

One small moment at a time.

{/* ── Right: login panel ───────────────────────── */}
🌱

Grateful Journal

A private space for gratitude and reflection.
No feeds. No noise. Just you and your thoughts.

🔒 End-to-end encrypted. We never read your entries.

{(error || authError) && (

{error || authError}

)}
) }