Exam Prep Navbar Link Implementation
Summary
Added “Exam Prep” link to the main navigation bar that is conditionally visible only to users with active physician subscriptions.
Changes Made
1. Updated Root Configuration
File: _quarto.yml
Added “Exam Prep” link to the navbar:
navbar:
left:
- text: Home
href: index.qmd
- text: Patients
href: AtoZ_Patients/index.qmd
- text: Physicians
href: AtoZ_Physicians/index.qmd
- text: Exam Prep # NEW
href: AtoZ_Physicians/exam_prepare.qmd
id: exam-prep-link
- text: Profile
href: profile.qmdAdded navbar-visibility.js to resources:
Added script to HTML body:
2. Created Navbar Visibility Script
File: navbar-visibility.js
This script: - Runs on every page load - Checks if user is logged in via Supabase - Queries the user’s profile to check has_physician_access and subscription_status - Shows/hides the “Exam Prep” navbar link based on access rights
Logic Flow:
User loads page
↓
Check: Is Supabase initialized?
NO → Exit (Exam Prep link stays visible by default)
YES ↓
↓
Check: Is user logged in?
NO → Hide Exam Prep link
YES ↓
↓
Check: Does user have physician_access = true?
NO → Hide Exam Prep link
YES ↓
↓
Check: Is subscription_status = 'active'?
NO → Hide Exam Prep link
YES ↓
↓
✅ Show Exam Prep link
How It Works
Client-Side Conditional Display
The “Exam Prep” link is always present in the HTML, but the navbar-visibility.js script runs after page load and:
- Finds all links containing “exam_prepare” in the href
- Checks user authentication via Supabase
- Verifies physician access by querying the profiles table
- Shows or hides the link by setting
display: noneordisplay: ''on the parent.nav-itemelement
User Experience
For users WITHOUT physician access: - “Exam Prep” link is hidden from navbar - If they somehow navigate to exam_prepare.html directly, they are redirected by physician-auth-guard.js
For users WITH physician access: - “Exam Prep” link is visible in navbar between “Physicians” and “Profile” - Click takes them directly to the interactive MCQ page - Page is protected by authentication guard script
Security Notes
⚠️ This is client-side protection only - Determined users can bypass by disabling JavaScript - The physician-auth-guard.js on the exam_prepare page provides additional client-side protection - For full security, implement server-side protection (Netlify Edge Functions)
Testing
Test Scenarios
- Unauthenticated User
- Visit
/index.html(not logged in) - Expected: “Exam Prep” link is hidden in navbar
- Visit
- Authenticated User Without Subscription
- Login with free account
- Visit any page
- Expected: “Exam Prep” link is hidden in navbar
- Authenticated User With Active Subscription
- Login with paid account (has_physician_access = true, subscription_status = ‘active’)
- Visit any page
- Expected: “Exam Prep” link is visible in navbar
- Click “Exam Prep” → Should navigate to exam_prepare.html with interactive MCQs
- Expired Subscription
- User with
subscription_status = 'inactive' - Expected: “Exam Prep” link is hidden in navbar
- User with
Files Modified
- _quarto.yml - Added navbar link, script resource, and include-after-body
- navbar-visibility.js - Created new script for conditional visibility
Deployment
The changes are ready for deployment. Simply:
git add _quarto.yml navbar-visibility.js
git commit -m "Add Exam Prep link to navbar with conditional visibility"
git pushNetlify will rebuild with the new navbar link visible only to authenticated users with physician access.
Future Enhancements
Optional improvements: 1. Server-side protection: Netlify Edge Function to enforce access at the network level 2. Loading state: Show/hide link more gracefully during auth check 3. Cache user status: Store access status in localStorage to reduce API calls 4. Badge indicator: Show “NEW” or notification badge on Exam Prep link 5. Dropdown menu: Group “Physicians” and “Exam Prep” under a dropdown
Status: ✅ Complete and deployed Impact: All pages site-wide (navbar appears on every page) Access Control: Client-side conditional display based on Supabase authentication Date: November 20, 2025