Patients, doctors, and admins access clinical records through separate portals
Translation pending
AI summary · README
HealthJavaScript · JavaGitHub @medicard67-specOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
medicard67-spec/nfc-medicard
Translation pending
Taken from the repository README
Loading the full README. The saved excerpt is shown below.
A secure clinical data portal built to accompany the NFC MediCard FYP report. Three role-based
portals (Patient, Doctor, Admin) built on:Read the full README ↗A secure clinical data portal built to accompany the NFC MediCard FYP report. Three role-based portals (Patient, Doctor, Admin) built on:
.github/workflows/ci.yml).| Video | What it shows |
|---|---|
| Overview (1:30) | What NFC MediCard is and how it works, in one compilation |
| Patient demo (1:32) | A patient's journey: card registration, check-in, the doctor's tap, and the patient app |
| Doctor walkthrough (1:18) | Dashboard, appointments, admissions and discharge, medication renewals, labs and imaging, referrals, and the tablet + USB reader |
| Admin walkthrough (1:12) | Hospital dashboard, adding patients and assigning cards, check-in queue and rooms, doctor accounts, data entry, reports, and the audit log |
supabase/schema.sql,
and run it. This creates all the tables (profiles, patients, doctors,
medical_history, lab_results, radiology, messages, appointments, vitals,
audit_log) with Row Level Security enabled and no client-facing policies — all access goes
through the backend's service-role key.
supabase/migration_002_audit_and_unread.sql
instead to pick up the new audit_log table and the messages.read column.npm run seed are still pre-confirmed regardless of this setting, so seeding and
local testing aren't affected either way.
Storage buckets (lab-results, radiology) are created automatically the first time the backend
starts — no manual setup needed.
cd server && cp .env.example .env
Edit server/.env and fill in SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY.
cd ../client && cp .env.example .env
Edit client/.env and fill in VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY (the anon key,
not the service role key).
cd server && npm install
cd ../client && npm install
From /server, with your .env filled in:
npm run seed
This creates demo accounts and sample clinical data directly in your Supabase project. Demo logins
(password for all: password123):
| Role | Notes | |
|---|---|---|
| Admin | [email protected] | |
| Doctor | [email protected] | Dr. Sarah Jenkins — Cardiology |
| Doctor | [email protected] | Dr. Robert Chan — Endocrinology |
| Patient | [email protected] | Card UID: 0443FADB3D0289 |
| Patient | [email protected] | Card UID: 07D8E9F0 |
Terminal 1 — Backend (from /server):
npm run dev
Runs on http://localhost:4001.
Terminal 2 — Frontend (from /client):
npm run dev
Runs on http://localhost:5173. Log in with any of the demo accounts above.
0443FADB3D0289 to pull up the seeded patient's full record.AABBCCDD) to register a brand-new
patient and bind it to that "card".jspdf)./api/doctor/stats.From /server:
npm test
Runs the Vitest + Supertest suite (auth middleware, patient CRUD, NFC lookup) against a mocked Supabase client — no real database or network access needed. The same command runs automatically on every push/PR via GitHub Actions.
nfc-medicard/
├── .github/workflows/ci.yml # Runs backend tests + frontend build on push/PR
├── docs/videos/ # Overview, patient demo, doctor and admin walkthroughs
├── supabase/
│ ├── schema.sql # Full schema + RLS (fresh setup)
│ └── migration_002_audit_and_unread.sql # Incremental migration (existing projects)
├── server/ # Express API (Supabase service-role client)
│ ├── test/ # Vitest + Supertest suite, mocked Supabase client
│ └── src/
│ ├── routes/ # patients, medical-history, lab-results, radiology,
│ │ # messages, nfc, appointments, admin, doctor, audit, users
│ ├── middleware/auth.js # verifies Supabase JWTs
│ ├── lib/ # supabase client, storage upload helper, audit log helper
│ └── seed.js
└── client/ # React app
└── src/
├── pages/{patient,doctor,admin}/
├── components/{MonthCalendar,QrCodeCard,QrScannerView}.jsx
├── context/{AuthContext,ThemeContext,ToastContext,UnreadContext}.jsx
└── lib/{supabase.js,api.js,webNfc.js,exportPdf.js}
All data access goes through the Express backend, which uses the Supabase service role key
(bypasses Row Level Security). The frontend only ever holds the anon key, used solely for
Supabase Auth (sign-in), and calls the backend with the resulting access token in the
Authorization: Bearer <token> header. The backend's own middleware (requireAuth /
requireRole) enforces who can see and modify what. Key mutating actions (registrations, NFC
scans, record/lab/imaging additions) are recorded to audit_log for accountability.
This deploys the frontend to Vercel (free) and the backend to Render (free tier), both connected to a GitHub repo so every push auto-deploys.
git init # if not already a repo
git add .
git commit -m "Initial commit"
Create a new empty repository on github.com/new, then:
git remote add origin <your-repo-url>
git branch -M main
git push -u origin main
server.npm install, start command npm start (or let Render auto-detect from
package.json).SUPABASE_URLSUPABASE_SERVICE_ROLE_KEYCLIENT_ORIGIN — set this after step 2 below, to your Vercel URL (comma-separate if you add
more origins later, e.g. https://app.vercel.app,https://yourdomain.com)PORT automatically — no need to add it.https://<something>.onrender.com URL — that's your VITE_API_URL base for the frontend
(append /api).client.npm run build, output dist
(defaults are correct).VITE_SUPABASE_URLVITE_SUPABASE_ANON_KEYVITE_API_URL — https://<your-render-app>.onrender.com/apihttps://<something>.vercel.app URL.Go back to Render and set CLIENT_ORIGIN to the Vercel URL from step 2 (this is what CORS checks
against), then redeploy the backend service so the change takes effect.
Your site is now live at the Vercel URL — share that with anyone to let them use the app.
The same React codebase can be wrapped into a native Android app with
Capacitor — no rewrite, no separate mobile codebase. The website keeps
working exactly as before; this just adds an installable .apk on top. (iOS isn't covered here —
building an iOS app requires Xcode, which only runs on macOS.)
Already set up in this repo:
client/capacitor.config.json — app id com.medicard.nfc, web dir dist.client/.env.production — overrides VITE_API_URL to point at the deployed Render backend
(instead of localhost) whenever npm run build runs, so the packaged app talks to production.client/android/ — the generated native Android project (gitignored: .gradle/, build/,
local.properties, and any local JDK under .tools/).cd client
npm run build # bundles the app with the production API URL baked in
npx cap sync android # copies the fresh web build into the native project
Then open the client/android folder in Android Studio, let Gradle sync, and go to
Build → Build Bundle(s) / APK(s) → Build APK(s). The resulting .apk can be sideloaded
directly onto any Android device — no Play Store submission needed.
Capacitor's Android WebView serves the app from the origin https://localhost. Add that to the
backend's CLIENT_ORIGIN environment variable on Render (comma-separated alongside the Vercel
URL) so the packaged app's API calls aren't rejected by CORS:
https://nfc-medicard-5y8u.vercel.app,https://localhost
For presenting somewhere with unreliable or no internet, there's a fully self-contained offline build — no Supabase, no Render, no Vercel, nothing outside your own laptop:
cd client && npm run build:offline # builds client/dist-offline against a local API
cd ../server && npm run offline # serves the app + a canned in-memory dataset on one port
Open http://localhost:4444 — same demo accounts as above ([email protected],
[email protected], [email protected] / password123, card UID 0443FADB3D0289). You can
disconnect Wi-Fi entirely and it keeps working: server/offline-server.js is a single Express
process serving both the built frontend and an in-memory stand-in for the API, seeded with the
same demo data as npm run seed. It's for a local demo only — the auth "token" it issues has no
real security, so never deploy this file or expose it beyond your own machine.
supabase.storage.from(bucket).createSignedUrl()).