# QueueMed — Salle d'attente virtuelle pour cabinets médicaux ## Architecture - **Frontend**: React 19, Vite 6, Tailwind CSS 4, shadcn/ui, wouter, Framer Motion, Recharts, Socket.io-client - **Backend**: Express 4, tRPC 11, Socket.io 4, Drizzle ORM - **Database**: MySQL 8 - **Auth**: JWT + session cookie (simple email/password login, no OAuth) - **QR Code**: qrcode npm package with rotating anti-cheat tokens - **Deploy**: Docker + docker-compose, Nginx Proxy Manager for HTTPS ## Theme — MEDICAL LIGHT - **Primary**: #10b981 (emerald-500) and #06b6d4 (cyan-500) - **Background**: white / #f0fdf4 (green-50) / #ecfeff (cyan-50) - **Cards**: white with subtle shadow, glass-morphism (backdrop-blur, bg-white/70) - **Accents**: #0d9488 (teal-600) for CTAs, #f97316 (orange-500) for alerts - **Feel**: clean, hygienic, medical — light green/cyan, translucent panels, rounded corners - **Font**: Inter (Google Fonts) ## Database Schema (see docs_ref/schema.ts) 5 tables: users, subscriptions, clinics, queueEntries, analyticsEvents ## Key Routes | Route | Page | Access | |---|---|---| | / | Landing page (hero, features, pricing, testimonials) | Public | | /login | Login page | Public | | /dashboard | Doctor dashboard (KPIs, clinic list, quick actions) | Auth | | /dashboard/clinics | Manage clinics (CRUD, QR code, settings) | Auth | | /dashboard/queue/:clinicId | Real-time queue management | Auth | | /dashboard/analytics | Charts, CSV export, AI recommendations | Auth | | /dashboard/subscription | Subscription plans, trial, blocking | Auth | | /display/:clinicId | Display screen for tablet/monitor | Public | | /queue/:token | Patient interface (live position, alerts) | Public | | /ticket/:entryId | Printable ticket | Public | ## Project Structure ``` /home/ubuntu/queue-med-deploy/ ├── client/ │ ├── src/ │ │ ├── main.tsx # React entry + wouter router │ │ ├── App.tsx # Layout shell │ │ ├── lib/ │ │ │ └── trpc.ts # tRPC client setup │ │ ├── components/ │ │ │ └── ui/ # shadcn/ui components │ │ ├── _core/ │ │ │ └── hooks/ │ │ │ └── useAuth.ts │ │ └── pages/ │ │ ├── Home.tsx # Landing │ │ ├── Login.tsx │ │ ├── Dashboard.tsx │ │ ├── DoctorClinics.tsx │ │ ├── QueueManagement.tsx │ │ ├── Analytics.tsx │ │ ├── PatientQueue.tsx │ │ ├── DisplayScreen.tsx │ │ ├── SubscriptionPage.tsx │ │ ├── PrintTicket.tsx │ │ ├── Onboarding.tsx │ │ ├── Help.tsx │ │ └── QrPoster.tsx │ └── index.html ├── server/ │ ├── _core/ │ │ ├── index.ts # Express + Socket.io server │ │ ├── trpc.ts # tRPC setup │ │ └── context.ts # Auth context │ ├── routers.ts # All tRPC procedures │ ├── db.ts # Drizzle helpers │ ├── schema.ts # Drizzle schema │ └── auth.ts # JWT auth logic ├── shared/ │ └── types.ts # Shared types ├── drizzle.config.ts ├── vite.config.ts ├── tsconfig.json ├── package.json ├── Dockerfile ├── docker-compose.yml └── .dockerignore ``` ## Environment Variables - DATABASE_URL — MySQL connection string - JWT_SECRET — Secret for JWT signing - PORT — Server port (default 5000) - NODE_ENV — production/development ## Socket.io Rooms - clinic:{clinicId} — Doctor + display screen - patient:{patientToken} — Individual patient - display:{clinicId} — Display screen only ## Commands - pnpm dev — Start dev server - pnpm build — Production build - pnpm db:push — Push Drizzle migrations - pnpm start — Start production server ## CRITICAL NOTES - Use existing pages in src_ref/ as reference for UI patterns and tRPC calls - The QR token rotation system is anti-cheat: tokens expire on schedule - Subscription middleware blocks sensitive procedures when expired - Socket.io is initialized in server/_core/index.ts and exposed globally