import { writeFileSync, mkdirSync } from "fs"; // ─── Updated login/page.tsx ────────────────────────────────────────────────── writeFileSync("app/login/page.tsx", `"use client"; import Link from "next/link"; import { useRouter, useSearchParams } from "next/navigation"; import { Suspense, useState } from "react"; import { PageSchema } from "../../components/page-schema"; import { SiteFooter } from "../../components/site-footer"; import { SiteHeader } from "../../components/site-header"; import { defaultFaqs } from "../../data/faq"; import { siteInfo } from "../../data/site"; import { storeAuthTokens } from "../../lib/api"; type ApiResponse = { data: T; meta: { timestamp: string; version: "v1" }; error: null | { message: string; code?: string }; }; type AuthData = { user: { id: string; email: string; fullName?: string; emailVerified?: boolean }; accessToken: string; refreshToken: string; requiresTwoFactor?: boolean; }; function LoginForm() { const router = useRouter(); const searchParams = useSearchParams(); const nextPath = searchParams.get("next") ?? "/app"; const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const [totpToken, setTotpToken] = useState(""); const [requiresTwoFactor, setRequiresTwoFactor] = useState(false); const [status, setStatus] = useState(""); const [isError, setIsError] = useState(false); const onSubmit = async (event: React.FormEvent) => { event.preventDefault(); setStatus("Signing in..."); setIsError(false); try { const res = await fetch("/api/auth/login", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email, password, ...(requiresTwoFactor ? { totpToken } : {}) }), }); const payload = (await res.json()) as ApiResponse; if (!res.ok || payload.error) { setStatus(payload.error?.message ?? "Login failed."); setIsError(true); return; } if (payload.data.requiresTwoFactor) { setRequiresTwoFactor(true); setStatus("Enter the code from your authenticator app."); return; } storeAuthTokens({ accessToken: payload.data.accessToken, refreshToken: payload.data.refreshToken, user: payload.data.user, }); setStatus(\`Welcome back, \${payload.data.user.email}\`); router.push(nextPath); } catch { setStatus("Login failed. Please try again."); setIsError(true); } }; return (
setEmail(e.target.value)} className="block w-full appearance-none rounded-lg border border-border bg-background/50 px-3 py-2 placeholder-muted-foreground shadow-sm focus:border-primary focus:outline-none focus:ring-primary sm:text-sm transition-all" />
setPassword(e.target.value)} className="block w-full appearance-none rounded-lg border border-border bg-background/50 px-3 py-2 placeholder-muted-foreground shadow-sm focus:border-primary focus:outline-none focus:ring-primary sm:text-sm transition-all" />
{requiresTwoFactor && (
setTotpToken(e.target.value.replace(/\\D/g, ""))} className="block w-full appearance-none rounded-lg border border-border bg-background/50 px-3 py-2 placeholder-muted-foreground shadow-sm focus:border-primary focus:outline-none focus:ring-primary sm:text-sm transition-all tracking-widest text-center" />
)}
Forgot your password?
{status && (

{status}

)}
); } export default function LoginPage() { const schema = [ { "@context": "https://schema.org", "@type": "WebPage", name: "LedgerOne Login", description: "Sign in to LedgerOne to access your audit-ready ledger.", url: \`\${siteInfo.url}/login\`, }, { "@context": "https://schema.org", "@type": "FAQPage", mainEntity: defaultFaqs.map((item) => ({ "@type": "Question", name: item.question, acceptedAnswer: { "@type": "Answer", text: item.answer }, })), }, ]; return (
L1

Sign in to your account

Or{" "} start your 14-day free trial

); } `); // ─── Updated register/page.tsx ─────────────────────────────────────────────── writeFileSync("app/register/page.tsx", `"use client"; import Link from "next/link"; import { useRouter } from "next/navigation"; import { useState, FormEvent } from "react"; import { PageSchema } from "../../components/page-schema"; import { SiteFooter } from "../../components/site-footer"; import { SiteHeader } from "../../components/site-header"; import { defaultFaqs } from "../../data/faq"; import { siteInfo } from "../../data/site"; import { storeAuthTokens } from "../../lib/api"; type ApiResponse = { data: T; meta: { timestamp: string; version: "v1" }; error: null | { message: string; code?: string }; }; type AuthData = { user: { id: string; email: string; fullName?: string }; accessToken: string; refreshToken: string; message?: string; }; export default function RegisterPage() { const router = useRouter(); const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const [status, setStatus] = useState(""); const [isError, setIsError] = useState(false); const schema = [ { "@context": "https://schema.org", "@type": "WebPage", name: "LedgerOne Create Account", description: "Create a LedgerOne account and start with two free accounts.", url: \`\${siteInfo.url}/register\`, }, { "@context": "https://schema.org", "@type": "FAQPage", mainEntity: defaultFaqs.map((item) => ({ "@type": "Question", name: item.question, acceptedAnswer: { "@type": "Answer", text: item.answer }, })), }, ]; const onSubmit = async (event: FormEvent) => { event.preventDefault(); setStatus("Creating account..."); setIsError(false); try { const res = await fetch("/api/auth/register", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email, password }), }); const payload = (await res.json()) as ApiResponse; if (!res.ok || payload.error) { setStatus(payload.error?.message ?? "Registration failed."); setIsError(true); return; } storeAuthTokens({ accessToken: payload.data.accessToken, refreshToken: payload.data.refreshToken, user: payload.data.user, }); setStatus("Account created! Please verify your email."); router.push("/app"); } catch { setStatus("Registration failed. Please try again."); setIsError(true); } }; return (
L1

Create your account

Already have an account?{" "} Sign in

setEmail(e.target.value)} className="block w-full appearance-none rounded-lg border border-border bg-background/50 px-3 py-2 placeholder-muted-foreground shadow-sm focus:border-primary focus:outline-none focus:ring-primary sm:text-sm transition-all" />
setPassword(e.target.value)} className="block w-full appearance-none rounded-lg border border-border bg-background/50 px-3 py-2 placeholder-muted-foreground shadow-sm focus:border-primary focus:outline-none focus:ring-primary sm:text-sm transition-all" />

Minimum 8 characters

{ const btn = document.getElementById("submit-btn") as HTMLButtonElement; if (btn) btn.disabled = !e.target.checked; }} />
{status && (

{status}

)}
); } `); // ─── New forgot-password/page.tsx ──────────────────────────────────────────── mkdirSync("app/forgot-password", { recursive: true }); writeFileSync("app/forgot-password/page.tsx", `"use client"; import Link from "next/link"; import { useState } from "react"; import { SiteFooter } from "../../components/site-footer"; import { SiteHeader } from "../../components/site-header"; type ApiResponse = { data: T; meta: { timestamp: string; version: "v1" }; error: null | { message: string; code?: string }; }; export default function ForgotPasswordPage() { const [email, setEmail] = useState(""); const [status, setStatus] = useState(""); const [sent, setSent] = useState(false); const [isError, setIsError] = useState(false); const onSubmit = async (event: React.FormEvent) => { event.preventDefault(); setStatus("Sending reset link..."); setIsError(false); try { const res = await fetch("/api/auth/forgot-password", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email }), }); const payload = (await res.json()) as ApiResponse<{ message: string }>; if (!res.ok && payload.error) { setStatus(payload.error.message ?? "Something went wrong."); setIsError(true); return; } setSent(true); setStatus(payload.data?.message ?? "If that email exists, a reset link has been sent."); } catch { setStatus("Something went wrong. Please try again."); setIsError(true); } }; return (
L1

Reset your password

Back to sign in

{sent ? (

{status}

Check your email inbox and spam folder.

Back to sign in
) : (

We'll send a reset link to this address if it has an account.

setEmail(e.target.value)} className="block w-full appearance-none rounded-lg border border-border bg-background/50 px-3 py-2 placeholder-muted-foreground shadow-sm focus:border-primary focus:outline-none focus:ring-primary sm:text-sm transition-all" />
{isError && status && (

{status}

)}
)}
); } `); // ─── New verify-email/page.tsx ─────────────────────────────────────────────── mkdirSync("app/verify-email", { recursive: true }); writeFileSync("app/verify-email/page.tsx", `"use client"; import Link from "next/link"; import { useSearchParams } from "next/navigation"; import { useEffect, useState, Suspense } from "react"; import { SiteFooter } from "../../components/site-footer"; import { SiteHeader } from "../../components/site-header"; type ApiResponse = { data: T; meta: { timestamp: string; version: "v1" }; error: null | { message: string; code?: string }; }; function VerifyEmailContent() { const searchParams = useSearchParams(); const token = searchParams.get("token"); const [status, setStatus] = useState<"loading" | "success" | "error">("loading"); const [message, setMessage] = useState(""); useEffect(() => { if (!token) { setStatus("error"); setMessage("No verification token provided."); return; } fetch(\`/api/auth/verify-email?token=\${encodeURIComponent(token)}\`) .then((res) => res.json() as Promise>) .then((payload) => { if (payload.error) { setStatus("error"); setMessage(payload.error.message ?? "Verification failed."); } else { setStatus("success"); setMessage(payload.data?.message ?? "Email verified successfully."); } }) .catch(() => { setStatus("error"); setMessage("Something went wrong. Please try again."); }); }, [token]); return (
{status === "loading" && ( <>

Verifying your email...

)} {status === "success" && ( <>

Email Verified!

{message}

Sign in )} {status === "error" && ( <>

Verification Failed

{message}

The link may have expired. Please register again or contact support.

Back to sign in )}
); } export default function VerifyEmailPage() { return (
L1

Email Verification

Loading...
}>
); } `); // ─── New reset-password/page.tsx ───────────────────────────────────────────── mkdirSync("app/reset-password", { recursive: true }); writeFileSync("app/reset-password/page.tsx", `"use client"; import Link from "next/link"; import { useRouter, useSearchParams } from "next/navigation"; import { Suspense, useState } from "react"; import { SiteFooter } from "../../components/site-footer"; import { SiteHeader } from "../../components/site-header"; type ApiResponse = { data: T; meta: { timestamp: string; version: "v1" }; error: null | { message: string; code?: string }; }; function ResetPasswordForm() { const router = useRouter(); const searchParams = useSearchParams(); const token = searchParams.get("token") ?? ""; const [password, setPassword] = useState(""); const [confirm, setConfirm] = useState(""); const [status, setStatus] = useState(""); const [isError, setIsError] = useState(false); const onSubmit = async (event: React.FormEvent) => { event.preventDefault(); if (password !== confirm) { setStatus("Passwords do not match."); setIsError(true); return; } if (password.length < 8) { setStatus("Password must be at least 8 characters."); setIsError(true); return; } if (!token) { setStatus("Missing reset token. Please use the link from your email."); setIsError(true); return; } setStatus("Resetting password..."); setIsError(false); try { const res = await fetch("/api/auth/reset-password", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ token, password }), }); const payload = (await res.json()) as ApiResponse<{ message: string }>; if (!res.ok || payload.error) { setStatus(payload.error?.message ?? "Reset failed. The link may have expired."); setIsError(true); return; } setStatus("Password reset successfully! Redirecting to sign in..."); setTimeout(() => router.push("/login"), 2000); } catch { setStatus("Something went wrong. Please try again."); setIsError(true); } }; if (!token) { return (

Invalid reset link. Please request a new one.

Request password reset
); } return (
setPassword(e.target.value)} className="block w-full appearance-none rounded-lg border border-border bg-background/50 px-3 py-2 placeholder-muted-foreground shadow-sm focus:border-primary focus:outline-none focus:ring-primary sm:text-sm transition-all" />

Minimum 8 characters

setConfirm(e.target.value)} className="block w-full appearance-none rounded-lg border border-border bg-background/50 px-3 py-2 placeholder-muted-foreground shadow-sm focus:border-primary focus:outline-none focus:ring-primary sm:text-sm transition-all" />
{status && (

{status}

)}
); } export default function ResetPasswordPage() { return (
L1

Set new password

Back to sign in

Loading...
}>
); } `); console.log("✅ login, register, forgot-password, verify-email, reset-password pages written");