A delightful patient management system built with Next.js and NestJS, featuring role-based access control, dockerized development environment, comprehensive test coverage and a beautiful responsive interface.
This project is built as a Turborepo monorepo containing:
- Frontend: Next.js, React, TypeScript, and Tailwind CSS
- Backend: NestJS, TypeScript, PostgreSQL, and Prisma ORM
- Shared: Common packages for TypeScript configs, ESLint rules and other shared utilities
- Framework: Next.js 15 with App Router
- UI Library: React 19 with TypeScript
- Styling: Tailwind CSS with custom design system
- Components: Shadcn UI
- State Management: TanStack React Query
- Forms: React Hook Form with Zod validation
- Icons: Lucide React
- Theming: Next Themes for dark/light mode
- Framework: NestJS with TypeScript
- Database: PostgreSQL with Prisma ORM
- Authentication: JWT with Passport.js
- Validation: Class Validator with DTOs
- Security: bcrypt for password hashing and role guards
- Monorepo: Turborepo
- Package Manager: Yarn Workspaces
- Testing: Jest with Testing Library
- Linting: ESLint with custom configs
- Formatting: Prettier
- Containerization: Docker
- Node.js: >= 24.7.0
- Yarn: 1.22.22
- Docker: For database and containerized development
git clone https://github.com/cmdrGuyson/patient-management-system.git
cd pms
yarn installCreate environment files for both the API and web applications by copying the example files:
# Copy environment files
cp apps/api/.env.example apps/api/.env
cp apps/web/.env.example apps/web/.envImportant Notes:
- The
.env.exampledata can be used for development purposes - Please replace all values for production use for security reasons
For the first time setup, you'll want to seed the database with initial users and patients:
SEED=true docker compose upThis will:
- Create an admin user (
admin@email.com) and regular user (user@email.com) - Seed the database with sample patient data from
apps/api/data/patients.json - Both users have the default password:
ozN1$dslBR
For subsequent development sessions (when you don't need to reseed):
docker compose uppms/
├── apps/
│ ├── web/ # Next.js frontend application
│ │ ├── src/
│ │ │ ├── app/ # Next.js App Router pages
│ │ │ │ ├── (auth)/ # Authentication routes
│ │ │ │ ├── (dashboard)/ # Protected dashboard routes
│ │ │ │ └── layout.tsx # Root layout
│ │ │ ├── components/ # React components
│ │ │ │ ├── features/ # Feature-specific components
│ │ │ │ ├── providers/ # Context providers
│ │ │ │ └── ui/ # Reusable UI components
│ │ │ ├── contexts/ # React contexts
│ │ │ ├── hooks/ # Custom React hooks
│ │ │ ├── lib/ # Utility functions and API client
│ │ │ ├── types/ # TypeScript type definitions
│ │ │ └── __tests__/ # Test files
│ │ │ ├── components/ # Component tests
│ │ │ ├── contexts/ # Context tests
│ │ │ └── integration/ # Integration tests
│ │ └── public/ # Static assets
│ └── api/ # NestJS backend API
│ ├── src/
│ │ ├── auth/ # Authentication module
│ │ ├── patients/ # Patient management module
│ │ ├── users/ # User management module
│ │ ├── prisma/ # Database service
│ │ └── config/ # Configuration module
│ ├── prisma/ # Database schema and migrations
│ ├── data/ # Seed data (patients.json)
│ └── test/ # E2E tests
├── packages/ # Shared packages
│ ├── ui/ # Shared UI components
│ ├── eslint-config/ # Shared ESLint configurations
│ └── typescript-config/ # Shared TypeScript configurations
├── docker-compose.yml # Development environment
├── docker-compose.test.yml # Testing environment
└── turbo.json # Turborepo configuration
- JWT-based authentication with configurable expiration
- Role-based access control with two roles:
ADMIN: Full CRUD access to all resourcesUSER: Read-only access to patient data
- Password hashing using bcrypt with salt rounds
- Protected routes using JWT guards and role decorators
- Context-based state management for authentication
- Permission-based UI rendering using
Cancomponent - Automatic token validation and refresh
- Route protection with automatic redirects
PATIENT_LIST: "patient:list"; // View patient list
PATIENT_VIEW: "patient:view"; // View individual patient
PATIENT_CREATE: "patient:create"; // Create new patients (Admin only)
PATIENT_UPDATE: "patient:update"; // Update patients (Admin only)
PATIENT_DELETE: "patient:delete"; // Delete patients (Admin only)id: Primary keyemail: Unique email addresspassword: Hashed passwordname: User display namerole: User role (ADMIN/USER)createdAt/updatedAt: Timestamps
id: Primary keyfirstName/lastName: Patient nameemail: Unique email addressphoneNumber: Contact numberdob: Date of birthadditionalInformation: Medical notescreatedAt/updatedAt: Timestamps
- Unit Tests: Service and controller logic
- E2E Tests: Full API endpoint testing
- Test Database: Isolated PostgreSQL instance for testing
- Component Tests: React component testing with Testing Library
- Integration Tests: User interaction flows
# Run all unit and integration tests
yarn test
# Run E2E tests for backend against test database
yarn test:e2e- Add paginated querying for patient list
- Add permission aware AI agent for patient related queries
Made with ❤️ by Gayanga Kuruppu
