Skip to content

Guest Mode

harshcode1 edited this page Jun 20, 2026 · 2 revisions

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.

Goals

  1. Zero friction — one click from the landing/login page into a fully populated app.
  2. Full reachability — every patient-facing page is browsable.
  3. Honest boundaries — any write action clearly prompts for sign-up instead of silently failing.
  4. Database safety — guests are never a real session; no writes are possible.

How it works

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.

State (in AuthContext)

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/register

On a real login or registration, clearGuest() runs so the guest flag never lingers for an authenticated user.

Demo data (lib/demoData.js)

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.

Page wiring pattern

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;

The auth-gate

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.

UI affordances

  • 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.

Why client-side only?

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.

Related

Clone this wiki locally