A Page Redirect Is Not a Substitute for an Inline Modal When the Page Has State
TLDR
Redirecting users to an auth landing page (/auth/login) when they click export inside a single-page web app completely destroys all in-memory work. The original developer added the redirect as a quick fallback because the auth modal was tightly coupled to the desktop shell component. We fixed the defect by extracting the modal into an autonomous, portable script (window.GxAuth.open()) that can be loaded on any page without destroying user state.
| Fallback Strategy | User Work Preservation | Code Complexity | UX Outcome |
|---|---|---|---|
window.location.href Redirect | Zero (Destroys DOM state & uploaded files) | Low (1 line of code) | Catastrophic (User loses work) |
Standalone GxAuth Modal Script | 100% (Preserves in-memory state during auth) | Low (Extracted clean API) | Uninterrupted (User resumes immediately) |
Full-page redirects wipe in-memory DOM state and file uploads
Imagine spending 15 minutes in a standalone PDF processor tool: uploading a complex multi-column document, tweaking extraction boundaries, correcting tabular data, and fine-tuning export options. Finally, you click Export.
Instead of opening a login dialog over your work, the browser immediately navigates to https://example.com/auth/login. After authenticating and navigating back, the workbench is empty. The uploaded file is gone, the corrections have vanished, and all work is lost.
The redirect was intentional. It was added as a fallback for standalone pages that lacked access to the desktop OS shell's internal modal component.
Tight modal coupling to host shells forces redirect shortcuts
The root cause was component coupling. The original auth modal had 140 lines of DOM construction code tied directly to the OS desktop shell (os-shell.js):
- It referenced DOM containers specific to the shell.
- It depended on global shell variables.
- It managed state inside the shell's window manager.
Legacy Flow (Page Redirect): User Tool Page (In-Memory State) Auth Page | | | |--- 1. Click Export ------------>| | | |--- 2. Redirect ------------>| (Page Reloads) | | (Wipes all work) |
Refactored Flow (Autonomous Modal): User Tool Page (In-Memory State) GxAuth Modal | | | |--- 1. Click Export ------------>| | | |--- 2. window.GxAuth.open() >| | |<-- 3. Show Modal Overlay ---| (State Preserved) |--- 4. Authenticate ------------>| | | |<-- 5. Resolve Promise ------| |<-- 6. File Exported ------------| |
When running a tool standalone outside the shell, the modal was unavailable. Developers took the easy way out and added window.location.href = '/auth/login'. But full page navigations reload the document context, wiping in-memory JavaScript state completely.
Standalone self-injecting modals preserve active page contexts
We extracted the auth modal into a standalone JavaScript module (assets/js/ginexys-auth-modal.js) with zero dependencies on host shells:
// BEFORE: Hardcoded fallback on standalone pages
window.location.href = '/auth/login'; // Destroys all in-memory work
// AFTER: Portable modal API preserving active page DOM window.GxAuth.open({ context: 'Sign in to save and export your work.', onSignIn: (user) => resolve({ signedIn: true, tier: user.tier }), });
Key refactoring steps
- Self-injecting DOM: The script automatically injects the modal markup into
document.bodyon its first invocation. - Namespace prefixes: All CSS classes and element IDs inside the component use
gx-auth-prefixes to eliminate collisions on host pages. - One-line shell delegation: The desktop shell deleted its 140 lines of internal DOM construction and delegates directly to
window.GxAuth.open().
Rule of thumb: Never use full-page URL redirects as a fallback when an action requires auth on a stateful page. Extract the modal into a portable component so user state is preserved throughout the auth flow.