// App shell — loads the session, applies the entry-routing rule (SD-0001 §6.5), and renders // the matching screen. The rule is exhaustive: no state lands nowhere (BUC-4). The verify // response carries the same shape as /me, so onAuthed feeds the session directly. import { useEffect, useState } from "react"; import { getMe, type StorefrontResult, type VerifyResult } from "./api"; import { routeFor, type SessionState } from "./routing"; import Admin from "./screens/Admin"; import CreateStorefront from "./screens/CreateStorefront"; import Landing from "./screens/Landing"; import SignIn from "./screens/SignIn"; type Door = "signup" | "login"; type Welcome = "new" | "back" | null; export default function App() { const [session, setSession] = useState(null); const [loading, setLoading] = useState(true); const [door, setDoor] = useState(null); const [welcome, setWelcome] = useState(null); async function reload() { setLoading(true); setSession(await getMe()); setLoading(false); } useEffect(() => { void reload(); }, []); if (loading) { return (

Loading…

); } const route = routeFor(session ?? { account: null, storefront: null }); if (route === "landing") { if (door) { return ( setDoor(null)} onAuthed={(result: VerifyResult) => { setWelcome(result.created ? "new" : "back"); setDoor(null); setSession({ account: result.account, storefront: result.storefront }); }} /> ); } return setDoor("signup")} onLogIn={() => setDoor("login")} />; } const email = session!.account!.email; function signedOut() { setWelcome(null); setDoor(null); setSession(null); } if (route === "create-storefront") { return ( { setWelcome(null); setSession({ account: { email }, storefront: sf }); }} onAlreadyOwns={() => void reload()} onSignedOut={signedOut} /> ); } return ( ); }