Auth Modal Without a Redirect: Extracting GxAuth from the OS Shell
TLDR
Bug: standalone tool pages redirected to /auth/login on export, destroying all in-memory work. Cause: no inline modal existed outside the shell. Fix: extracted GxAuth as a shared component that injects an inline modal into any page.
Symptom
On a standalone tool page (direct navigation to /tools/pdf-processor/ without the OS shell), clicking Export redirected to the sign-in page. The PDF was gone. The extraction was gone. The user had to re-upload and re-process after signing in.
Root Cause
The OS shell had a fully working auth modal. _buildAuthModal() constructed a gx-modal-overlay and appended it to document.body. It worked because the shell owned the page.
Standalone tool pages had no auth UI at all. ginexys-gate.js called window.location.href = '/auth/login' as the fallback. That redirect killed all in-memory state.
The modal code was not portable because it was deeply entangled with shell internals: it read _authUser, called _closeAuthModal(), used shell-specific element IDs, and depended on os-shell.js already being loaded.
The Fix
Extract the modal into ginexys-auth.js. This file has no dependency on the shell. It uses %%SUPABASE_URL%% and %%SUPABASE_ANON_KEY%% tokens replaced at build time, and nothing else from the portfolio codebase.
Public API:
window.GxAuth.open({ context, onSignIn })
window.GxAuth.close()
window.GxAuth.hasSession()
All modal element IDs are prefixed gxauth- to avoid collision with the shell's gx-modal-* elements on pages where both load.
The shell's _openAuthModal() was replaced with a one-line delegation:
function _openAuthModal() {
GxAuth.open({ context: 'Sign in to continue.', onSignIn: _initAuth });
}
The 140-line _buildAuthModal was deleted.
Guard
Load order matters. On the shell page, ginexys-auth.js must load before os-shell.js. On standalone tool pages, it must load before ginexys-gate.js. Both scripts use defer, which preserves script-tag order. Keep ginexys-auth.js above os-shell.js and above ginexys-gate.js in every HTML that loads them.
Lesson
When a UI component exists in one place and you need it in three places, extract it. A redirect is not a substitute for an inline modal when the page has state worth preserving.