Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
3822343
docs: add design spec for magic-link-first auth flow
tomusdrw Apr 10, 2026
fc3729c
docs: add implementation plan for magic-link-first auth flow
tomusdrw Apr 10, 2026
234c476
test: add AuthFlow tests for magic-link-first redesign
tomusdrw Apr 11, 2026
e82f03e
feat: redesign AuthFlow to magic-link-first
tomusdrw Apr 11, 2026
bb278f8
test: add AuthCallback tests
tomusdrw Apr 11, 2026
0e72f6d
feat: add AuthCallback component for magic link redirects
tomusdrw Apr 11, 2026
5a4fa98
test: add PasswordUpdate tests
tomusdrw Apr 11, 2026
d99bdb9
feat: add PasswordUpdate component for settings
tomusdrw Apr 11, 2026
4edd4bd
feat: add password management to Settings
tomusdrw Apr 11, 2026
5b401f8
feat: export AuthCallback and PasswordUpdate from supabase
tomusdrw Apr 11, 2026
9ce2fce
docs: update AuthFlow stories for magic-link-first design
tomusdrw Apr 11, 2026
af8eb20
feat: update demo app with magic link auth callback
tomusdrw Apr 11, 2026
b871567
fix: remove unused vi import from AuthFlow tests
tomusdrw Apr 11, 2026
cdf80ed
fix: AuthCallback race condition + update docs
tomusdrw Apr 11, 2026
7ed5f03
feat: add Supabase config with custom email templates
tomusdrw Apr 13, 2026
3ebf9fe
fix: align config.toml with production Supabase settings
tomusdrw Apr 13, 2026
c818c87
chore: add supabase .gitignore
tomusdrw Apr 14, 2026
6c64e13
fix: address CodeRabbit review comments
tomusdrw Apr 14, 2026
58b06a3
docs: update plan with portable paths and reviewed code fixes
tomusdrw Apr 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions demo/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { initializeTheme } from "../../lib/components/DarkMode";
import { SupabaseProvider } from "../../lib/supabase/SupabaseProvider";
import { UserMenu } from "../../lib/supabase/UserMenu";
import { AuthFlow } from "../../lib/supabase/AuthFlow";
import { AuthCallback } from "../../lib/supabase/AuthCallback";
import { Settings } from "../../lib/supabase/Settings";
import { SubscriptionStatus } from "../../lib/supabase/SubscriptionStatus";
import { PricingCard } from "../../lib/supabase/PricingCard";
Expand All @@ -22,7 +23,7 @@ const SUPABASE_ANON_KEY = import.meta.env.VITE_SUPABASE_ANON_KEY || "";

initializeTheme();

type Page = "home" | "login" | "settings" | "pricing" | "gated";
type Page = "home" | "login" | "settings" | "pricing" | "gated" | "auth-callback";

export function App() {
if (!SUPABASE_URL || !SUPABASE_ANON_KEY) {
Expand All @@ -46,8 +47,14 @@ export function App() {
);
}

const AUTH_CALLBACK_PATH = new URL("auth/callback", document.baseURI).pathname;
const HOME_PATH = new URL(".", document.baseURI).pathname;

function DemoApp() {
const [page, setPage] = useState<Page>("home");
const [page, setPage] = useState<Page>(() => {
if (window.location.pathname === AUTH_CALLBACK_PATH) return "auth-callback";
return "home";
Comment on lines +54 to +56
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Avoid hardcoding root-relative callback URLs in the demo.

These paths assume the app is served from /. If the demo is hosted under a basename, the magic link will redirect to the wrong URL and replaceState("/", ...) will navigate out of the app instead of back to the demo home.

Suggested fix
+const AUTH_CALLBACK_URL = new URL("auth/callback", document.baseURI);
+const HOME_URL = new URL(".", document.baseURI);
+
 function DemoApp() {
   const [page, setPage] = useState<Page>(() => {
-    if (window.location.pathname === "/auth/callback") return "auth-callback";
+    if (window.location.pathname === AUTH_CALLBACK_URL.pathname) return "auth-callback";
     return "home";
   });
@@
         <AuthCallback
           onSuccess={() => {
-            window.history.replaceState({}, "", "/");
+            window.history.replaceState({}, "", HOME_URL.pathname);
             setPage("home");
           }}
         />
@@
-      <AuthFlow onSuccess={onSuccess} redirectTo={window.location.origin + "/auth/callback"} />
+      <AuthFlow onSuccess={onSuccess} redirectTo={AUTH_CALLBACK_URL.toString()} />

Also applies to: 84-90, 142-142

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@demo/src/App.tsx` around lines 51 - 53, The code hardcodes root-relative
paths ("/auth/callback" and "/") which break when the app is served under a
basename; update all checks and navigations (the useState initializer that
examines window.location.pathname, the other pathname checks around lines ~84-90
and ~142, and the history/replaceState usage) to compute paths relative to the
app base instead of exact "/" matches — for example derive the app base from a
reliable source (import.meta.env.BASE_URL or
document.querySelector('base')?.getAttribute('href') || '') or use
pathname.endsWith('/auth/callback') for detection, and when calling replaceState
or navigating, prepend that base (or use a relative path) so the magic-link
callback detection and history replacement work correctly regardless of the
app's basename.

});

return (
<div className="flex min-h-screen flex-col">
Expand Down Expand Up @@ -77,6 +84,15 @@ function PageContent({ page, setPage }: { page: Page; setPage: (p: Page) => void
return <PricingPage />;
case "gated":
return <GatedFeaturePage />;
case "auth-callback":
return (
<AuthCallback
onSuccess={() => {
window.history.replaceState({}, "", HOME_PATH);
setPage("home");
}}
/>
);
default:
return <HomePage setPage={setPage} />;
}
Expand Down Expand Up @@ -126,7 +142,7 @@ function HomePage({ setPage }: { setPage: (p: Page) => void }) {
function LoginPage({ onSuccess }: { onSuccess: () => void }) {
return (
<div className="mx-auto max-w-sm pt-8">
<AuthFlow onSuccess={onSuccess} />
<AuthFlow onSuccess={onSuccess} redirectTo={new URL("auth/callback", document.baseURI).toString()} />
</div>
);
}
Expand Down
Loading