
A secure patient management system for healthcare practitioners
Modern, privacy-focused application for managing patient records and generating professional invoices.
Features β’ Tech Stack β’ Getting Started β’ Development β’ Deployment
My Patients is a full-stack web application designed to help healthcare practitioners manage their patient records securely. Built with a focus on data privacy and security, it provides encrypted storage for sensitive patient information including social security numbers, along with automated invoice generation capabilities.
This is a personal project built to explore modern web technologies including Rust backend development and secure cryptographic practices.
- Secure Patient Records - Store patient information with AES-GCM encryption for sensitive data
- SSN Protection - Double-layer security with encrypted storage and hashed indexing for fast, secure lookups
- Multi-Office Support - Manage patients across multiple practitioner offices
- PDF Invoices - Generate professional PDF invoices with native Rust PDF generation
- Digital Signatures - Add practitioner signatures to invoices
- Business Information - Complete practitioner business details integration
- Rust - Systems programming language for performance and safety
- Loco - Rails-inspired web framework for Rust
- SeaORM - Async ORM for database operations
- PostgreSQL - Primary database (SQLite supported for development)
- TypeScript - Type-safe JavaScript
- Vite - Fast build tool
- Bun - JavaScript runtime and package manager
- React 19 - UI library
- TanStack - Type-safe routing
- Tailwind CSS 4 - Utility-first CSS framework
- ShadCN - Accessible UI components
- React Hook Form - Form management with Zod validation
- AES-GCM - Symmetric encryption for sensitive data
- Argon2 - Password hashing
- Base64 - Encoding for encrypted data
- Docker - Multi-stage optimized builds
- Google Cloud Run - Serverless container deployment
- Distroless Images - Minimal attack surface for production
- Rust 1.88+ (Install)
- Bun (Install)
- PostgreSQL 15+ or SQLite for development
- Docker (optional, for containerized deployment)
Create a .env
file in the root directory:
# Database
DATABASE_URL=postgres://user:password@localhost:5432/my_patients
# Encryption Keys (generate secure random keys)
ENCRYPTION_KEY=your-32-byte-base64-encoded-key
SSN_SALT_KEY=your-secure-salt-key
# JWT
JWT_SECRET=your-jwt-secret-key
# Supabase Storage (optional, for invoice storage)
SUPABASE_URL=your-supabase-url
SUPABASE_KEY=your-supabase-key
SUPABASE_BUCKET=your-bucket-name
- Clone the repository
git clone https://github.com/yourusername/my_patients.git
cd my_patients
- Install backend dependencies
cargo build
- Install frontend dependencies
cd frontend
bun install
- Run database migrations
cargo loco db migrate
- Start the development servers
In one terminal (backend):
cargo loco start
In another terminal (frontend):
cd frontend
bun run dev
The application will be available at http://localhost:5173
(frontend) with API at http://localhost:5150
(backend).
my_patients/
βββ src/
β βββ app.rs # Application setup & routing
β βββ controllers/ # HTTP request handlers
β βββ models/ # Database models & business logic
β βββ services/ # Business services (crypto, invoice, etc.)
β βββ validators/ # Request validation logic
β βββ workers/ # Background job workers
β βββ middlewares/ # Custom middleware
βββ frontend/
β βββ src/
β β βββ routes/ # TanStack Router routes
β β βββ components/ # React components
β β βββ api/ # API client & types
β β βββ hooks/ # Custom React hooks
β β βββ i18n/ # Translations
β βββ public/ # Static assets
βββ migration/ # Database migrations
βββ config/ # Environment configurations
βββ dockerfile # Multi-stage production build
Create a new migration:
cargo loco db generate migration_name
Run migrations:
cargo loco db migrate
Rollback last migration:
cargo loco db down
Backend linting:
cargo clippy
cargo fmt
Frontend linting:
cd frontend
bun run lint
Run Rust tests:
cargo test
The project includes an optimized multi-stage Dockerfile:
# Build the image
docker build -t my-patients .
# Run the container
docker run -p 5150:5150 --env-file .env my-patients
The Dockerfile uses:
- cargo-chef for faster Rust dependency caching
- Bun for fast frontend builds
- Distroless base image for minimal attack surface
- Multi-stage builds for optimal layer caching
Using the dockerfile
file, you can build your Docker container image.
From the oven/bun
image, build the frontend. β Apple users: disable the Use Rosetta for x86_64/amd64 emulation on Apple Silicon from the Docker Desktop settings. We will build a linux/amd64
image and its seems that tailwind has issues with Apple Rosetta to build our CSS.
From the rust
image, build the backend.
Then copy all the files from the frontend and backend builds into a new distroless/cc-debian12
image.
localhost
won't work for the host in production as you will access the service from outside the container (with a ping on the domain name that will point to the container). Thus the host must be0.0.0.0
.- For the CORS configuration, you can set the
Access-Control-Allow-Origin
header to*
or to your Google Cloud Run domain (as it is Client Side Rendering).
- When running a simple
cargo run --release
, the binary is built for the host architecture. If you want to build it for a specific target, you can usecargo build --release --target x86_64-unknown-linux-gnu
(or any other target). Google Cloud Run usesx86_64-unknown-linux-gnu
as the target architecture, so you should build your binary for that target. - The docker image architecture must be a
linux/amd64
image. When running a simpledocker build . -t test
, it will build the image for the host architecture. If you want to build it for a specific target, you can usedocker build . -t test --platform linux/amd64
(or any other target).
Prerequisites: your docker image must be pulled on a public or private registry accessible by Google Cloud Run. For instance, you can use Docker Hub (just push your built image to your Docker Hub account).
To deploy your application on Google Cloud Run, visit the Google Cloud Console and follow these steps:
- Create a global project if you don't have one.
- Enable the Cloud Run API.
- Visit the Cloud Run page and click on "Deploy a container".
Service Configuration:
- Container image URL: the URL of your Docker image (e.g.,
your-id/your-image-name
). - Service name: the name of your service (e.g.,
my-app
). - Region: select the region where you want to deploy your service (e.g.,
europe-west9
). - Authentication: If you want to use JWT authentication, you can allow unauthenticated invocations.
- Billing: First option, serverless, is the best option for small applications.
Then proceed to the container configuration.
Container Configuration:
- Container port: set the Google Cloud Run default port (8080).
β οΈ Theserver.port
value must be read from the PORT Google Cloud Run env variable. Otherwise, you app would not be able to restart properly after a cold start. To do that change the hardcoded from to{{ get_env(name="PORT", default="5150") }}
. - Environment variables: you can set environment variables for your application (e.g.,
DATABASE_URL
,JWT_SECRET
,LOCO_ENV
etc.). - Health checks: you can enable health checks to ensure your service is running correctly. In our case, select HTTP and the path to your health check endpoint. Don't forget to add a small delay because your application might take some time to start up (e.g., 10 seconds).
Then proceed to the last steps.
- Revision scaling: reduce the number of instances to 3 (can be changed later to upgrade)
This project is provided as-is for educational and personal use.