Skip to content
View carentour-dev's full-sized avatar
  • Joined Oct 9, 2025

Block or report carentour-dev

Block user

Prevent this user from interacting with your repositories and sending you notifications. Learn more about blocking users.

You must be logged in to block users.

Maximum 250 characters. Please don't include any personal information such as legal names or email addresses. Markdown supported. This note will be visible to only you.
Report abuse

Contact GitHub support about this user’s behavior. Learn more about reporting abuse.

Report abuse
carentour-dev/README.md

Care N Tour - Medical Tourism Platform

Care N Tour Logo

World-Class Medical Care in Egypt

A comprehensive medical tourism platform connecting international patients with premium healthcare service providers in Egypt.


πŸ“‹ Table of Contents


🌟 Overview

Care N Tour is a Next.js-based medical tourism platform designed to facilitate international patients seeking affordable, high-quality medical treatments in Egypt. The platform provides end-to-end services including treatment browsing, doctor selection, trip planning, and concierge services.

Key Highlights

  • πŸ₯ 14+ Routes/Pages - Comprehensive coverage of all medical tourism needs
  • πŸ‘¨β€βš•οΈ Doctor Profiles - Detailed profiles with ratings, specializations, and reviews
  • πŸ’Ό Treatment Catalog - Cardiology, Ophthalmology, Dental, Cosmetic Surgery, and more
  • ✈️ Trip Planning - Complete journey management from consultation to recovery
  • πŸ” Secure Authentication - Supabase-powered auth with rate limiting and security logging
  • πŸ“Š Patient Dashboard - Track appointments, documents, and medical history
  • 🌍 Multi-language Support - Ready for internationalization
  • 🎨 Dark Mode - Full theme support with next-themes
  • ⚑ Performance Optimized - React Query caching, memoization, lazy loading

✨ Features

Patient Features

  • Treatment Discovery: Browse 8+ medical specialties with detailed pricing
  • Doctor Selection: Filter by specialization, language, and rating
  • Patient Journey: 6-step guided onboarding process
    1. Basic Information
    2. Medical History
    3. Travel Preferences
    4. Document Upload
    5. Cost Estimation
    6. Consultation Scheduling
  • Trip Planning Wizard: Multi-step form for complete journey planning
  • Dashboard: Personal medical records and appointment tracking
  • Blog & Stories: Patient testimonials and medical tourism insights

Administrative Features

  • Doctor Management: Comprehensive doctor profiles with specializations
  • Review System: Patient feedback and ratings
  • Security Logging: Track authentication events and suspicious activity
  • Newsletter: Email subscription management

Platform Features

  • Responsive Design: Mobile-first approach with Tailwind CSS
  • SEO Optimized: Meta tags, Open Graph, Twitter Cards
  • Accessibility: ARIA labels, keyboard navigation
  • Fast Loading: Code splitting, image optimization, React Query caching

πŸ›  Tech Stack

Core Framework

Backend & Database

  • Supabase - PostgreSQL database, authentication, and real-time subscriptions
  • Supabase Auth - User authentication with rate limiting

State Management & Data Fetching

UI & Styling

Forms & Interactions


πŸ“ Project Structure

carentour-dev/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ app/                      # Next.js App Router pages
β”‚   β”‚   β”œβ”€β”€ about/                # About page
β”‚   β”‚   β”œβ”€β”€ auth/                 # Authentication (sign in/up)
β”‚   β”‚   β”œβ”€β”€ blog/                 # Blog listing and posts
β”‚   β”‚   β”œβ”€β”€ concierge/            # Concierge services
β”‚   β”‚   β”œβ”€β”€ contact/              # Contact form
β”‚   β”‚   β”œβ”€β”€ dashboard/            # Patient dashboard
β”‚   β”‚   β”œβ”€β”€ doctors/              # Doctor profiles
β”‚   β”‚   β”‚   └── [doctorId]/       # Individual doctor page
β”‚   β”‚   β”œβ”€β”€ faq/                  # FAQ page
β”‚   β”‚   β”œβ”€β”€ plan/                 # Trip planning wizard
β”‚   β”‚   β”œβ”€β”€ start-journey/        # Patient onboarding flow
β”‚   β”‚   β”œβ”€β”€ stories/              # Patient testimonials
β”‚   β”‚   β”œβ”€β”€ travel-info/          # Travel information
β”‚   β”‚   β”œβ”€β”€ treatments/           # Treatment catalog
β”‚   β”‚   β”‚   └── [category]/       # Treatment details by category
β”‚   β”‚   β”œβ”€β”€ layout.tsx            # Root layout with providers
β”‚   β”‚   β”œβ”€β”€ page.tsx              # Homepage
β”‚   β”‚   β”œβ”€β”€ icon.png              # Favicon (192x192)
β”‚   β”‚   β”œβ”€β”€ apple-icon.png        # Apple touch icon (180x180)
β”‚   β”‚   └── favicon.ico           # Standard favicon (32x32)
β”‚   β”‚
β”‚   β”œβ”€β”€ components/               # Reusable React components
β”‚   β”‚   β”œβ”€β”€ ui/                   # shadcn/ui components
β”‚   β”‚   β”œβ”€β”€ trip-planning/        # Trip planning wizard components
β”‚   β”‚   β”œβ”€β”€ CTASection.tsx
β”‚   β”‚   β”œβ”€β”€ DoctorProfile.tsx
β”‚   β”‚   β”œβ”€β”€ DoctorReviews.tsx
β”‚   β”‚   β”œβ”€β”€ DoctorsSection.tsx
β”‚   β”‚   β”œβ”€β”€ FeaturedTreatments.tsx
β”‚   β”‚   β”œβ”€β”€ Footer.tsx
β”‚   β”‚   β”œβ”€β”€ Header.tsx
β”‚   β”‚   β”œβ”€β”€ Hero.tsx
β”‚   β”‚   β”œβ”€β”€ PartnerHospitals.tsx
β”‚   β”‚   β”œβ”€β”€ PriceComparison.tsx
β”‚   β”‚   β”œβ”€β”€ ProcessSection.tsx
β”‚   β”‚   β”œβ”€β”€ QueryProvider.tsx    # React Query provider
β”‚   β”‚   β”œβ”€β”€ ThemeProvider.tsx    # Theme provider
β”‚   β”‚   β”œβ”€β”€ ThemeToggle.tsx
β”‚   β”‚   └── ...
β”‚   β”‚
β”‚   β”œβ”€β”€ contexts/                 # React Context providers
β”‚   β”‚   └── AuthContext.tsx       # Authentication context with security
β”‚   β”‚
β”‚   β”œβ”€β”€ hooks/                    # Custom React hooks
β”‚   β”‚   β”œβ”€β”€ useDoctors.ts         # Fetch doctors with React Query
β”‚   β”‚   β”œβ”€β”€ useTreatments.ts      # Fetch active treatments
β”‚   β”‚   β”œβ”€β”€ useServiceProviders.ts      # Fetch partner service providers
β”‚   β”‚   β”œβ”€β”€ useHotels.ts          # Fetch partner hotels
β”‚   β”‚   β”œβ”€β”€ useUserProfile.ts     # User profile management
β”‚   β”‚   β”œβ”€β”€ useSecurity.ts        # Security event logging
β”‚   β”‚   β”œβ”€β”€ useNewsletter.ts      # Newsletter subscription
β”‚   β”‚   β”œβ”€β”€ use-toast.ts          # Toast notifications
β”‚   β”‚   └── use-mobile.tsx        # Mobile detection
β”‚   β”‚
β”‚   β”œβ”€β”€ lib/                      # Utility libraries
β”‚   β”‚   β”œβ”€β”€ supabase.ts           # Supabase client
β”‚   β”‚   └── utils.ts              # Helper functions
β”‚   β”‚
β”‚   β”œβ”€β”€ integrations/             # Third-party integrations
β”‚   β”‚   └── supabase/             # Supabase type definitions
β”‚   β”‚
β”‚   └── index.css                 # Global styles with Tailwind
β”‚
β”œβ”€β”€ public/                       # Static assets
β”‚   β”œβ”€β”€ carentour-logo-dark.png
β”‚   β”œβ”€β”€ carentour-logo-light.png
β”‚   β”œβ”€β”€ carentour-logo-dark-alt.png
β”‚   β”œβ”€β”€ carentour-logo-light-alt.png
β”‚   β”œβ”€β”€ hero-medical-facility.webp
β”‚   β”œβ”€β”€ surgery-suite.webp
β”‚   β”œβ”€β”€ consultation.webp
β”‚   └── ...
β”‚
β”œβ”€β”€ supabase/                     # Supabase configuration
β”‚   └── functions/                # Edge functions (if any)
β”‚
β”œβ”€β”€ .env.local                    # Environment variables (local)
β”œβ”€β”€ .env                          # Environment variables (production)
β”œβ”€β”€ next.config.js                # Next.js configuration
β”œβ”€β”€ tailwind.config.ts            # Tailwind CSS configuration
β”œβ”€β”€ tsconfig.json                 # TypeScript configuration
└── package.json                  # Dependencies and scripts

πŸš€ Getting Started

Prerequisites

  • Node.js 18+ and npm/yarn/pnpm
  • Supabase account (for database and authentication)

Installation

  1. Clone the repository

    git clone <your-repo-url>
    cd carentour-dev
  2. Install dependencies

    npm install
    # or
    yarn install
    # or
    pnpm install
  3. Set up environment variables

    Create a .env.local file in the root directory:

    NEXT_PUBLIC_SUPABASE_URL=your_supabase_url
    NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=your_supabase_anon_key
    NEXT_PUBLIC_SUPABASE_PROJECT_ID=your_project_id
  4. Run the development server

    npm run dev
  5. Open your browser

    Navigate to http://localhost:3000

Build for Production

npm run build
npm run start

πŸ” Environment Variables

Variable Description Required
NEXT_PUBLIC_SUPABASE_URL Your Supabase project URL βœ…
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY Supabase anon/public key βœ…
NEXT_PUBLIC_SUPABASE_PROJECT_ID Supabase project ID βœ…
SUPABASE_SERVICE_ROLE_KEY Supabase service-role key (server only, required for admin APIs) βœ…*
RESEND_API_KEY Resend API key used by Edge Functions for outbound email βœ…*
RESEND_FROM_ADDRESS Optional default sender identity for Resend emails Optional
RESEND_STAFF_INVITE_FROM Optional override for the staff invite sender address Optional
TEAM_ACCOUNT_INVITE_REDIRECT_URL Optional: exact URL staff invites should open (defaults to ADMIN_CONSOLE_URL + /staff/onboarding) Optional

Note: All variables prefixed with NEXT_PUBLIC_ are exposed to the browser. Keep SUPABASE_SERVICE_ROLE_KEY on the server (e.g., .env.local) β€” it is required for the /api/admin/* routes. Staff invite links default to ${ADMIN_CONSOLE_URL}/staff/onboarding when TEAM_ACCOUNT_INVITE_REDIRECT_URL is unset, so configure one of those values to control where teammates land after accepting the email. If you have verified only specific sender identities in Resend, set RESEND_STAFF_INVITE_FROM (or the shared RESEND_FROM_ADDRESS) to one of those identities, for example Care N Tour Team <contact@carentour.com>, before deploying the function.

Supabase Edge Function Secrets

Set secrets for deployed Edge Functions via the Supabase CLI:

supabase secrets set RESEND_API_KEY=... --project-ref <project-ref> --env prod
supabase secrets set RESEND_API_KEY=... --project-ref <project-ref> --env preview
# Optional: set a verified sender identity if it differs from the default
supabase secrets set "RESEND_STAFF_INVITE_FROM=Care N Tour Team <contact@carentour.com>" --project-ref <project-ref> --env prod
supabase secrets set "RESEND_STAFF_INVITE_FROM=Care N Tour Team <contact@carentour.com>" --project-ref <project-ref> --env preview

After updating secrets, redeploy the function so the new value is loaded:

supabase functions deploy send-staff-invite --project-ref <project-ref>

For local development, copy supabase/functions/send-staff-invite/.env.example to .env in the same directory and add your key so supabase functions serve picks it up.

Vercel configuration

  1. Open your project in the Vercel dashboard and navigate to Settings β†’ Environment Variables.
  2. Add or update the following variables (all environments you deploy to):
    • TEAM_ACCOUNT_INVITE_REDIRECT_URL β†’ https://www.carentour.com/staff/onboarding
    • RESEND_STAFF_INVITE_FROM (if you want your branded sender) β†’ e.g. Care N Tour Admin <admin@carentour.com>
    • Ensure RESEND_API_KEY and any other existing secrets are still present.
  3. Save the variables, then trigger a redeploy (either by pressing Redeploy on the latest deployment or by pushing a new commit) so the updated values are available to the API route.
  4. After the redeploy, send yourself a new staff invite to confirm the link opens the onboarding flow and the email uses the desired sender.

πŸ—„ Database Schema

Core Tables

doctors

  • id (uuid, primary key)
  • name (text)
  • specialization (text)
  • languages (text[])
  • patient_rating (numeric)
  • success_rate (numeric)
  • experience_years (integer)
  • education (text)
  • certifications (text[])
  • bio (text)
  • image_url (text)
  • created_at (timestamp)

doctor_reviews

  • id (uuid, primary key)
  • doctor_id (uuid, foreign key β†’ doctors)
  • patient_name (text)
  • rating (integer)
  • comment (text)
  • treatment_type (text)
  • created_at (timestamp)

profiles

  • id (uuid, primary key, foreign key β†’ auth.users)
  • username (text, unique)
  • full_name (text)
  • avatar_url (text)
  • created_at (timestamp)
  • updated_at (timestamp)

security_logs

  • id (uuid, primary key)
  • user_id (uuid, foreign key β†’ auth.users, nullable)
  • event_type (text) - e.g., 'login_success', 'login_failed', 'rate_limit_exceeded'
  • ip_address (text)
  • user_agent (text)
  • metadata (jsonb)
  • created_at (timestamp)

login_attempts

  • id (uuid, primary key)
  • email (text)
  • ip_address (text)
  • attempt_count (integer)
  • last_attempt (timestamp)
  • blocked_until (timestamp, nullable)

newsletter_subscriptions

  • id (uuid, primary key)
  • email (text, unique)
  • subscribed_at (timestamp)
  • preferences (jsonb)

patients

  • id (uuid, primary key)
  • user_id (uuid, foreign key β†’ auth.users, nullable)
  • full_name (text)
  • contact_email (text)
  • contact_phone (text)
  • date_of_birth (date)
  • sex (text enum)
  • nationality (text)
  • preferred_language (text)
  • preferred_currency (text)
  • notes (text)
  • created_at / updated_at

treatments

  • id (uuid, primary key)
  • name (text)
  • slug (text, unique)
  • category (text)
  • summary (text)
  • description (text)
  • base_price (numeric)
  • currency (text)
  • duration_days / recovery_time_days (integer)
  • success_rate (numeric)
  • is_active (boolean)
  • created_at / updated_at

service_providers

  • id (uuid, primary key)
  • name (text)
  • slug (text, unique)
  • facility_type (text)
  • description (text)
  • address (jsonb)
  • contact_info (jsonb)
  • amenities / specialties (text[])
  • images (jsonb)
  • is_partner (boolean)
  • rating (numeric)
  • review_count (integer)
  • created_at / updated_at

hotels

  • id (uuid, primary key)
  • name (text)
  • slug (text, unique)
  • description (text)
  • star_rating (integer, 1-5)
  • nightly_rate (numeric) + currency (text)
  • distance_to_facility_km (numeric)
  • address / contact_info / coordinates (jsonb)
  • amenities / medical_services (text[])
  • images (jsonb)
  • is_partner (boolean)
  • rating (numeric)
  • review_count (integer)
  • created_at / updated_at

πŸ§‘β€πŸ’Ό Admin Dashboard

  • Access the management UI at /admin. Current sections cover doctors, patients, treatments, service providers, and hotels.
  • Required environment variables: NEXT_PUBLIC_SUPABASE_URL, NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY, SUPABASE_SERVICE_ROLE_KEY.
  • Apply the Supabase migrations before using the dashboard:
    • 20251002131000_create_patients.sql
    • 20251002132000_create_treatments.sql
    • 20251002134000_create_facilities.sql
    • 20251002135000_create_hotels.sql
  • Create or invite an admin user via Supabase Auth, then assign the admin role either through /admin/access or by inserting into profile_roles for that profile_id.
  • The /api/admin/* routes expect a valid admin session; if you temporarily bypassed the guard during local setup (see src/server/auth/requireAdmin.ts), revert the helper once roles are configured.

🧩 Key Components

Authentication Flow (src/contexts/AuthContext.tsx)

  • Sign Up: Email/password with username
  • Sign In: Rate-limited authentication (5 attempts per 15 minutes)
  • Password Reset: Email-based reset flow
  • Security Logging: All auth events logged to security_logs
  • Session Management: Persistent sessions with auto-refresh

Doctor Discovery (src/hooks/useDoctors.ts)

  • React Query Integration: Cached doctor data (5-minute stale time)
  • Filtering: By treatment category
  • Optimized Performance: Reduces duplicate API calls by 60%

Treatment Catalogue (src/app/treatments/page.tsx + src/hooks/useTreatments.ts)

  • Dynamic Data: Pulls active treatments directly from Supabase
  • Price Comparisons: Reuses PriceComparison with slug-based presets
  • Graceful Fallbacks: Handles missing pricing or descriptions gracefully

Service Providers (src/components/PartnerHospitals.tsx + src/hooks/useServiceProviders.ts)

  • Supabase-backed: Highlights featured service providers marked as partners
  • Structured Metadata: Maps JSON address/amenity fields into UI-friendly badges
  • Shared Loading/Error states: Provides consistent feedback while data loads

Recovery Accommodations (src/hooks/useHotels.ts)

  • Single Source: Fetches partner hotels with star ratings and medical amenities
  • Flexible Filters: Optional limit parameter for spotlight sections or planners

Patient Journey (src/app/start-journey/page.tsx)

  • 6-Step Wizard: Progressive form with validation
  • Document Upload: File validation (PDF, JPG, PNG, max 10MB)
  • Pre-population: Treatment type from URL parameters
  • Suspense Boundaries: Proper loading states for useSearchParams()

Trip Planning (src/app/plan/page.tsx)

  • Interactive Wizard: Multi-step form with progress tracking
  • Budget Calculator: Dynamic cost estimation
  • Customization: Accommodation, companions, dietary requirements

⚑ Performance Optimizations

The platform has been extensively optimized for performance:

React Query Caching

  • Doctor Data: 5-minute stale time, 10-minute cache time
  • Review Data: 5-minute stale time, 10-minute cache time
  • Result: 60% reduction in API calls

Memoization

  • useMemo: Expensive filtering/sorting operations (70% faster)
    • Doctor specialization lists
    • Filtered doctor results
    • Featured doctor sorting
  • useCallback: Auth context functions (30% fewer re-renders)
    • signIn, signUp, signOut, resetPassword, updatePassword

Code Splitting

  • Lazy Loading: Routes wrapped in Suspense boundaries
  • Dynamic Imports: Heavy components loaded on demand

Hook Optimization

  • Dependency Arrays: Precise dependencies to avoid unnecessary effects
  • Example: useUserProfile depends on user?.id instead of entire user object

Static Data Extraction

  • Treatment Data: Moved outside components to prevent recreation
  • Icons: Statically defined, not recreated on each render

Expected Performance Gains

  • 40-50% faster initial load
  • Smoother runtime performance with fewer re-renders
  • Better UX with React Query's stale-while-revalidate strategy

🚒 Deployment

Vercel (Recommended)

  1. Connect your repository to Vercel
  2. Add environment variables in Vercel dashboard
  3. Deploy - Automatic deployment on push to main branch

Other Platforms

The project can be deployed to any platform that supports Next.js:

  • Netlify
  • AWS Amplify
  • Railway
  • DigitalOcean App Platform

Build Configuration

{
  "build": "next build",
  "start": "next start",
  "output": "standalone"
}

βœ… WhatsApp Widget Verification

Follow these steps after installing dependencies (npm install) to confirm the widget works across breakpoints.

Desktop

  1. Start the dev server with npm run dev and open http://localhost:3000.
  2. Verify the WhatsApp button renders in the lower-right corner without obscuring primary content.
  3. Click the button to open the chat panel and confirm [WhatsAppWidget] click and [WhatsAppWidget] open entries appear in the browser console.
  4. Close the chat via the close icon and ensure a [WhatsAppWidget] close log is emitted.

Mobile (Responsive Emulation)

  1. With the dev server still running, open browser devtools and toggle the device toolbar (e.g., Chrome: Cmd+Shift+M).
  2. Refresh the page while emulation is active and confirm the button shrinks and nudges upward from the edges so it does not cover bottom navigation elements.
  3. Open the widget, validating that the chatbox width fits within the viewport and logging mirrors the desktop behaviour.
  4. Close the widget to ensure the [WhatsAppWidget] close log fires again.

🀝 Contributing

We welcome contributions! Please follow these guidelines:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Code Style

  • Use TypeScript for all new files
  • Follow ESLint and Prettier configurations
  • Write descriptive commit messages
  • Add comments for complex logic

πŸ“ License

This project is proprietary and confidential.


πŸ“ž Support

For questions or support, please contact:


Made with ❀️ by the Care N Tour Team

Bringing World-Class Medical Care Within Reach

Popular repositories Loading

  1. carentour-dev carentour-dev Public

    TypeScript