- SUMMARY.md created for 24-02 (auth prompt modal, render-first root, public setup viewing) - STATE.md updated: plan advanced, progress 100%, decisions recorded - ROADMAP.md updated: phase 24 complete (2/2 plans with SUMMARYs) - REQUIREMENTS.md: PUBL-01 through PUBL-05 marked complete
4.6 KiB
phase, plan, subsystem, tags, dependency_graph, tech_stack, key_files, decisions, metrics
| phase | plan | subsystem | tags | dependency_graph | tech_stack | key_files | decisions | metrics | |||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 24-public-access-infrastructure | 02 | client/auth |
|
|
|
|
|
|
Phase 24 Plan 02: Public Access Infrastructure — Client Layer Summary
Public-first browsing implemented: anonymous visitors see content immediately, write actions show a friendly sign-in/sign-up prompt, and the setup detail page renders read-only for unauthenticated users via a dedicated public API endpoint.
Tasks Completed
| # | Task | Commit | Files |
|---|---|---|---|
| 1 | Add auth prompt state, modal, usePublicSetup hook, guard onboarding | cd85715 |
uiStore.ts, AuthPromptModal.tsx, useSetups.ts, useSettings.ts |
| 2 | Rework __root.tsx, guard write actions on catalog and setup pages | 7b0efae |
__root.tsx, $globalItemId.tsx, $setupId.tsx |
| 3 | Verify public access flows (auto-approved in auto mode) | — | — |
What Was Built
uiStore.ts
Extended with showAuthPrompt/openAuthPrompt/closeAuthPrompt state following the existing Zustand boolean modal pattern.
AuthPromptModal.tsx
New component rendered globally in __root.tsx. Fixed overlay with centered card, backdrop click-to-close, Escape key dismiss. Two buttons ("Sign in" and "Create account") both pointing to /login — Logto handles both flows at the same OIDC endpoint.
usePublicSetup hook
Added to useSetups.ts. Calls GET /api/setups/:id/public with enabled: setupId != null guard and 404-aware retry logic. Returns SetupWithItems shape identical to the private endpoint.
useOnboardingComplete(enabled)
Reworked from useSetting("onboardingComplete") delegation to a direct useQuery call that accepts an enabled parameter. Prevents auth-gated settings query from firing for anonymous users.
__root.tsx
- Removed
authLoadingspinner gate — app renders immediately for all visitors - Expanded
isPublicRouteto include/,/global-items/*,/setups/*,/users/*,/login - Replaced
window.location.href = "/login"withnavigate({ to: "/login" })(soft redirect, only fires after auth resolves and!authLoading) - Removed
onboardingLoadingspinner gate - Passes
isAuthenticatedtouseOnboardingComplete()as theenabledparam - Added
<AuthPromptModal />to JSX for global availability
global-items/$globalItemId.tsx
"Add to Collection" and "Add to Thread" buttons now check isAuthenticated before executing. Unauthenticated users see the AuthPromptModal instead.
setups/$setupId.tsx
- Conditionally uses
useSetup(authenticated) orusePublicSetup(anonymous) - All write action UI elements wrapped in
{isAuthenticated && ...}guards: Add Items button, Public toggle, Delete Setup button and confirmation dialog, empty-state Add Items button - ItemCard
onRemoveandonClassificationCycleprops areundefinedfor anonymous users - ItemPicker rendered only for authenticated users
Deviations from Plan
None — plan executed exactly as written.
Verification
bun run lint: 0 errors insrc/(4 pre-existing.obsidian/format errors)bun test: 247 pass, 15 fail — identical to pre-change baseline (failures are pre-existingwithImageUrlmodule issue in storage service, unrelated to this plan)
Known Stubs
None. The public setup endpoint (/api/setups/:id/public) must exist server-side for usePublicSetup to work — this is the responsibility of Plan 24-01 (server-side public access routes). If that plan has not yet run, anonymous users will see an error state instead of the setup content.