Accounts Phase 1c: sign-in UI, magic-link landing, auth store

- Shared reactive auth store (auth.user) + postJSON helper (sends the cookie).
- SignIn modal: email -> "check your inbox" (calm, no password); Google slots in
  here in Phase 2.
- /auth/verify route exchanges the magic-link token for a session, then home.
- Header shows "Sign in" or an account avatar; the You sheet gains "Signed in as
  …" + Sign out (or a Sign in row). Anonymous browsing is unchanged.
This commit is contained in:
jay
2026-06-03 01:19:30 +00:00
parent d2ae56dc65
commit 9237180608
6 changed files with 310 additions and 2 deletions
+35
View File
@@ -0,0 +1,35 @@
// Shared, reactive auth state (Svelte 5 runes in a module). Components read
// `auth.user` and it stays reactive across the app.
import { getJSON, postJSON } from './api.js';
export const auth = $state({ user: null, ready: false });
export async function refresh() {
try {
auth.user = await getJSON('/api/auth/me');
} catch {
auth.user = null;
} finally {
auth.ready = true;
}
}
// Request a magic link. Reply is intentionally identical for any address.
export function startEmail(email) {
return postJSON('/api/auth/email/start', { email });
}
// Exchange a magic-link token for a session (cookie set server-side).
export async function verifyToken(token) {
const res = await postJSON('/api/auth/email/verify', { token });
auth.user = res.user;
return res;
}
export async function logout() {
try {
await postJSON('/api/auth/logout', {});
} finally {
auth.user = null;
}
}