-
Notifications
You must be signed in to change notification settings - Fork 0
Guest Mode
Guest Mode lets anyone — recruiters, reviewers, curious visitors — explore the entire product with realistic data without creating an account, while ensuring no guest activity ever touches the database.
- Zero friction — one click from the landing/login page into a fully populated app.
- Full reachability — every patient-facing page is browsable.
- Honest boundaries — any write action clearly prompts for sign-up instead of silently failing.
- Database safety — guests are never a real session; no writes are possible.
Guest Mode is implemented entirely client-side. No fake server session or demo user is created — user stays null. Instead, AuthContext tracks a separate isGuest flag.
isGuest // boolean, persisted in localStorage ("bm_guest")
enterGuestMode() // set flag, persist, route to /dashboard
exitGuestMode() // clear flag, route away
requireRealUser() // the auth-gate (below)
guestPrompt // { action } | null → drives the modal
clearGuest() // called automatically on real login/registerOn a real login or registration, clearGuest() runs so the guest flag never lingers for an authenticated user.
Pure, deterministic generators (seeded pseudo-random for stable output) that match each API's response shape exactly:
| Generator | Feeds | Notes |
|---|---|---|
demoMoods(days) |
Dashboard, Mood | ~30 days with a gentle upward "recovery" trend |
demoAssessments() |
Dashboard, History, Details | 5 PHQ-9/GAD-7 results trending downward (improving) |
demoDoctors() |
Doctors list | 6 verified specialists with ratings/reviews |
demoAppointments() |
Appointments | upcoming, pending, past & cancelled |
demoChat() |
AI Chat | a sample anxiety/sleep conversation |
Because the demo objects mirror the real API shapes, pages render them with no special-casing in the presentational components.
Every guest-enabled page follows the same minimal change:
// 1. Don't redirect guests to /login
useEffect(() => {
if (!authLoading && !user && !isGuest) router.push('/login?redirect=…');
}, [user, authLoading, isGuest]);
// 2. Use demo data for guests, real fetch for users
useEffect(() => {
if (user) fetchData();
else if (isGuest) { setData(demoX()); setLoading(false); }
}, [user, isGuest]);
// 3. Don't blank out the page for guests
if (!user && !isGuest) return null;Write actions call requireRealUser('<action>'):
const handleSubmit = (e) => {
e.preventDefault();
if (!requireRealUser('save your mood')) return; // opens the modal for guests
// …real submit for authenticated users…
};For a real user it returns true and the action proceeds. For a guest it sets guestPrompt and returns false, which surfaces a global modal: “Sign in to {action}” with Create free account / Sign in / Keep exploring.
Gated actions include: saving a mood, sending an AI chat message, booking/cancelling an appointment, syncing Google Calendar. Taking an assessment is allowed (results compute live) but the save step is skipped for guests.
- Entry points: an “Explore as Guest” button on the landing hero and the login page.
-
GuestBanner— a sticky banner under the navbar ("Guest mode — you're viewing demo data") with Create account and Exit. - Navbar — guests get the full patient navigation plus a "Guest" indicator and a Sign In button.
-
GuestGateModal— the global sign-in prompt, mounted once in the root layout.
Keeping Guest Mode out of the server means:
- The database is structurally incapable of receiving guest writes.
- No cleanup jobs for throwaway demo accounts.
- Auth, RBAC, and the real data path stay completely untouched and uncomplicated.