Production-grade healthcare appointment platform built with the MERN stack and deployed with a complete Docker + AWS + CI/CD workflow.
Live Application β’ Admin Panel β’ Source Code
Prescripto is a full-stack healthcare appointment platform connecting patients, doctors, and administrators through role-based workflows.
Patients can discover doctors, view profiles, manage their accounts, book appointments, and make online payments. Doctors can manage availability and appointments. Administrators can manage doctors, appointments, and platform activity.
The project goes beyond a typical MERN application: it is containerized, continuously built, published to GitHub Container Registry, deployed to AWS EC2, served through Nginx, secured with HTTPS, and operated with a SHA-based release workflow.
Production URL: https://prescripto.shop/
- User registration and authentication
- Browse doctors by specialty
- View doctor profiles
- Appointment booking
- Appointment management
- Profile management
- Online appointment payments with Razorpay
- Protected user workflows
- Secure doctor authentication
- Doctor dashboard
- Appointment statistics
- Earnings information
- View and manage appointments
- Complete or cancel appointments
- Availability management
- Profile management
- Secure admin authentication
- Platform dashboard
- Dashboard analytics
- Add doctors
- Manage doctors
- Manage appointments
- Monitor platform activity
- Razorpay order creation
- Browser-side Razorpay Checkout initialization
- Payment response handling
- Backend payment verification
- Production payment flow
- Multipart file uploads with Multer
- Cloudinary-based media storage
Internet
β
βΌ
βββββββββββββββββββββββ
β prescripto.shop β
β HTTPS / TLS β
ββββββββββββ¬βββββββββββ
β
βΌ
βββββββββββββββ
β Nginx β
β Reverse β
β Proxy β
ββββββββ¬βββββββ
β
βββββββββββββββββββΌββββββββββββββββββ
β β β
βΌ βΌ βΌ
/ /admin/ /api/
β β β
βΌ βΌ βΌ
βββββββββββββ βββββββββββββ βββββββββββββ
β Frontend β β Admin β β Backend β
β :5173 β β :5174 β β :4000 β
βββββββββββββ βββββββββββββ βββββββ¬ββββββ
β
βββββββββββββ΄ββββββββββββ
βΌ βΌ
MongoDB Razorpay
| Route | Destination |
|---|---|
/ |
Frontend β 127.0.0.1:5173 |
/admin/ |
Admin β 127.0.0.1:5174 |
/api/ |
Backend β 127.0.0.1:4000 |
The application ports are bound to localhost. Nginx is the public entry point.
Prescripto currently runs on:
- AWS EC2
- Amazon Linux 2023
- Docker + Docker Compose
- Nginx
- Let's Encrypt / Certbot
- GitHub Actions
- GitHub Container Registry (GHCR)
- Custom domain:
prescripto.shop
GitHub
β
β push to main
βΌ
GitHub Actions
β
βββ Install dependencies
βββ Lint
βββ Build frontend
βββ Build admin
βββ Build Docker images
βββ Push images to GHCR
β
βΌ
SSH to EC2
β
βΌ
deploy.sh
β
βββ Pull latest main
βββ Set IMAGE_TAG
βββ docker compose pull
βββ docker compose up -d
βββ Prune unused images
βββ Health check
The production application consists of three containers:
prescripto-backend
prescripto-frontend
prescripto-admin
Production port mappings:
Backend 127.0.0.1:4000 β container:4000
Frontend 127.0.0.1:5173 β container:4173
Admin 127.0.0.1:5174 β container:4173
The frontend and admin applications are built with Vite and served with Vite Preview inside their containers.
Images are tagged with the Git commit SHA instead of relying only on latest:
ghcr.io/vishwak-tech/prescripto-backend:<commit-sha>
ghcr.io/vishwak-tech/prescripto-frontend:<commit-sha>
ghcr.io/vishwak-tech/prescripto-admin:<commit-sha>
This provides traceable releases and supports deterministic rollback.
Every push to main triggers the production workflow.
git push
β
βΌ
Checkout
β
βΌ
Install dependencies
β
βΌ
Lint
β
βΌ
Build frontend + admin
β
βΌ
Docker build
β
βΌ
Push images to GHCR
β
βΌ
SSH to EC2
β
βΌ
Deploy with deploy.sh
β
βΌ
Health check
β
βΌ
Production
- Checkout source
- Set up Node.js
- Run
npm ci - Lint frontend
- Lint admin
- Build frontend
- Build admin
- Authenticate to GHCR
- Build backend/frontend/admin images
- Push SHA-tagged images
- Deploy the selected release to EC2
The deployment script uses:
set -eso a failed command stops the deployment sequence.
A post-deployment health check verifies that the application is reachable through Nginx.
Only the intended public entry points are exposed:
22 β SSH
80 β HTTP
443 β HTTPS
Application services remain bound to localhost:
127.0.0.1:4000
127.0.0.1:5173
127.0.0.1:5174
Production access uses SSH key authentication.
Configured SSH hardening includes:
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
Production backend secrets are stored outside Git in:
backend/.env
The production file uses restrictive permissions:
-rw-------
Do not commit .env files or private credentials.
The Razorpay Key ID is a public client-side configuration value required by Razorpay Checkout.
The Razorpay Key Secret must never be exposed in frontend code or a VITE_* variable. It belongs on the backend/server side.
Patient
β
βΌ
Request appointment payment
β
βΌ
Backend creates Razorpay order
β
βΌ
Frontend receives order
β
βΌ
Razorpay Checkout opens
β
βΌ
Payment completed
β
βΌ
Frontend receives payment response
β
βΌ
Backend verifies payment
β
βΌ
Appointment/payment state updated
The production payment flow has been tested successfully.
Production domain:
https://prescripto.shop/
DNS:
A @ β EC2 public IP
CNAME www β prescripto.shop
HTTP traffic is redirected to HTTPS.
HTTPS is provided using Let's Encrypt and Certbot.
The certificate covers:
prescripto.shop
www.prescripto.shop
Automatic renewal is enabled through the Certbot systemd timer.
Validation commands:
sudo nginx -t
sudo certbot certificates
sudo certbot renew --dry-runprescripto/
βββ frontend/ # Patient-facing React application
β βββ src/
β βββ public/
β βββ Dockerfile
β βββ package.json
β
βββ admin/ # Admin React application
β βββ src/
β βββ public/
β βββ Dockerfile
β βββ package.json
β
βββ backend/ # Express REST API
β βββ config/
β βββ controllers/
β βββ middleware/
β βββ models/
β βββ routes/
β βββ Dockerfile
β βββ package.json
β
βββ .github/
β βββ workflows/
β βββ deploy.yml # CI/CD pipeline
β
βββ docker-compose.yml # Production service definitions
βββ README.md
βββ .gitignore
The exact folder structure may evolve as the application grows.
| Layer | Technology |
|---|---|
| Frontend | React 19, Vite, Tailwind CSS, Axios |
| Admin | React, Vite, Tailwind CSS |
| Backend | Node.js, Express.js |
| Database | MongoDB, Mongoose |
| Authentication | JWT, bcrypt |
| File Uploads | Multer |
| Media Storage | Cloudinary |
| Payments | Razorpay |
| Containers | Docker, Docker Compose |
| CI/CD | GitHub Actions |
| Registry | GitHub Container Registry |
| Cloud | AWS EC2 |
| Reverse Proxy | Nginx |
| DNS | Hostinger DNS |
| TLS | Let's Encrypt / Certbot |
Install:
- Node.js
- npm
- Git
- MongoDB or access to a MongoDB deployment
- Cloudinary account
- Razorpay account if payment functionality is required
git clone https://github.com/Vishwak-Tech/prescripto.git
cd prescriptocd backend
npm installCreate backend/.env with the variables required by the backend configuration, for example:
MONGODB_URI=
JWT_SECRET=
CLOUDINARY_CLOUD_NAME=
CLOUDINARY_API_KEY=
CLOUDINARY_API_SECRET=
RAZORPAY_KEY_ID=
RAZORPAY_KEY_SECRET=Use the variable names expected by the current backend code. Never commit real values.
Start the backend using the project's configured development command, for example:
npm run servercd frontend
npm installCreate:
frontend/.env
Example:
VITE_BACKEND_URL=http://localhost:4000
VITE_RAZORPAY_KEY_ID=Start:
npm run devcd admin
npm installCreate:
admin/.env
Example:
VITE_BACKEND_URL=http://localhost:4000Start:
npm run devAutomated testing is the next planned improvement for Prescripto.
The intended testing strategy is:
Unit Tests
β
Component Tests
β
API / Integration Tests
β
End-to-End Tests
β
CI
β
Build
β
Docker
β
Deploy
- React Testing Library
- User interactions
- Forms and validation
- Protected UI states
- Critical appointment flows
- API integration tests
- Authentication/authorization
- Appointment endpoints
- Doctor endpoints
- Payment verification
- Patient login
- Doctor discovery
- Appointment booking
- Payment flow
- Admin workflows
Tests should pass before a production deployment is allowed.
The production system has been audited after deployment.
https://prescripto.shop/ β 200 OK
https://prescripto.shop/admin/ β 200 OK
https://prescripto.shop/api/admin/dashboard β 200 OK
All three services were verified running:
Backend
Frontend
Admin
Verified:
Server Is Running on PORT 4000
Database Connected
Verified:
systemctl status nginx
nginx -t
Verified:
- Valid certificate
prescripto.shopwww.prescripto.shop- Automatic renewal timer enabled
- Renewal dry-run completed successfully
Verified:
- Application ports bound to localhost
- SSH key authentication
- Root SSH login disabled
- Password SSH authentication disabled
- Backend
.envprotected with restrictive permissions
Current single-server deployment is intentionally lightweight.
The production audit identified:
- CPU load: low
- RAM: limited by the
t3.microsize - Disk: monitor growth as Docker images/logs accumulate
Every release is identified by its Git commit SHA.
Example:
Release A β 77fc010...
Release B β 2fcf70b...
Release C β 8031091...
Release D β 9f201d7...
Release E β 3b0e6bf...
If a future release causes a production issue, a verified previous SHA can be redeployed:
cd ~/prescripto
./deploy.sh <KNOWN_GOOD_COMMIT_SHA>The deployment script then pulls the corresponding images and recreates the services.
Using:
image:<commit-sha>
instead of only:
image:latest
makes releases:
- Traceable
- Auditable
- Easier to debug
- Easier to roll back
docker pscd ~/prescripto
docker compose psdocker compose logs --tail=50 backenddocker compose logs --tail=30 frontenddocker compose logs --tail=30 adminsudo systemctl status nginx --no-pager
sudo nginx -tsudo ss -tulpnfree -hdf -huptimesudo certbot certificates- MERN full-stack application
- Patient workflows
- Doctor workflows
- Admin dashboard
- JWT authentication
- Role-based authorization
- Appointment scheduling
- Razorpay payments
- Cloudinary media
- Dockerization
- Docker Compose
- AWS EC2 deployment
- Nginx reverse proxy
- Custom domain
- HTTPS / TLS
- GitHub Actions CI/CD
- GHCR image registry
- SHA-based releases
- Production security hardening
- Production troubleshooting
- Rollback strategy
- Unit testing
- React Testing Library coverage
- Backend integration/API tests
- End-to-end testing
- Test-gated CI/CD
- Infrastructure as Code with Terraform
- Better production observability
- Automated alerting
- Database backup/recovery strategy
- Advanced AWS architecture
- Horizontal scaling when required
Contributions are welcome.
git checkout -b feature/your-featuregit add .
git commit -m "feat: describe your change"git push origin feature/your-featureKeep pull requests focused and explain the motivation and impact of the change.
Full Stack Developer | Backend | DevOps | AI
- GitHub: https://github.com/Vishwak-Tech
- LinkedIn: https://www.linkedin.com/in/vishwak-koleti-tech
- Production: https://prescripto.shop/
Prescripto represents an end-to-end engineering workflow:
DEVELOPMENT
β
βΌ
Git
β
βΌ
GitHub
β
βΌ
GitHub Actions
CI / Build
β
βΌ
Docker
β
βΌ
GHCR
β
βΌ
AWS EC2
β
βΌ
Nginx
β
βΌ
HTTPS / TLS
β
βΌ
prescripto.shop
Built not only to demonstrate full-stack development, but to demonstrate how a real application can be packaged, deployed, secured, automated, verified, and operated in production.
Built with β€οΈ by Vishwak Koleti