A modern, high-performance web application built for health workers, providing an intuitive interface for managing healthcare workflows and patient interactions.
- Frontend Framework: React 19 with TypeScript
- Build Tool: Vite 7.1.3 (optimized for performance)
- Package Manager: Yarn
- Language: TypeScript (strict mode enabled)
- Styling: CSS with modern design principles
- Testing: Vitest + React Testing Library (100% coverage required)
- State Management: React useReducer with centralized reducers
- Code Quality: ESLint + Prettier + Husky pre-commit hooks
- Node.js (version 18 or higher)
- Yarn package manager
- VS Code (recommended editor)
# Clone the repository
git clone <repository-url>
cd ih-hw-webapp
# Install dependencies
yarn install
# Start development server
yarn devyarn dev- Start development server with hot reloadyarn build- Build for production (optimized)yarn lint- Run ESLint for code qualityyarn lint:fix- Auto-fix ESLint issuesyarn format- Format code with Prettieryarn format:check- Check code formattingyarn preview- Preview production build locallyyarn analyze- Analyze bundle size and composition (generates visual report)yarn type-check- Run TypeScript type checkingyarn pre-commit- Run all pre-commit checks manually (formatting, linting, type-check, tests, build)
yarn test- Run tests in watch modeyarn test:ui- Run tests with Vitest UIyarn test:run- Run tests onceyarn test:coverage- Run tests with coverage report (100% required)yarn test:watch- Run tests in watch mode
This project uses Husky to enforce code quality standards before each commit. The pre-commit hook automatically runs:
- Code Formatting & Linting - Formats and lints staged files using ESLint and Prettier
- Type Checking - Runs TypeScript type checking (
yarn type-check) - Tests - Executes all tests (
yarn test:run) - Build Verification - Ensures the project builds successfully (
yarn build)
Benefits:
- β Prevents broken code from being committed
- β Ensures consistent code style
- β Catches type errors early
- β Maintains test coverage
- β Guarantees build success
Note: All checks must pass before a commit is allowed. If any check fails, the commit will be blocked until issues are resolved.
- Development: http://localhost:3000 (optimized port)
- Production: [To be configured]
Create a .env file based on .env.example:
# Development
VITE_API_URL=http://localhost:3000
VITE_APP_ENV=development
# Production
VITE_API_URL=https://api.production.com
VITE_SENTRY_DSN=your_production_dsn
VITE_APP_ENV=productionEnvironment Variables:
VITE_API_URL- Backend API endpointVITE_SENTRY_DSN- Sentry error tracking DSN (production only)VITE_APP_ENV- Application environment (development/staging/production)
Note: VITE_SENTRY_DSN is only required in production. Sentry is automatically disabled in development for better performance.
ih-hw-webapp/
βββ src/
β βββ App.tsx # Main application component (optimized with memo)
β βββ main.tsx # Application entry point
β βββ App.css # Main application styles
β βββ assets/ # Static assets
β βββ components/ # Reusable UI components
β βββ config/ # Configuration files
β βββ services/ # HTTP and API services
β βββ hooks/ # Custom React hooks
β βββ types/ # Common TypeScript types
β βββ reducers/ # Common state reducers
β βββ utils/ # Utility functions (storage, etc.)
β βββ test/ # Test utilities and setup
β βββ examples/ # Development examples and patterns
β β βββ http-examples.tsx # HTTP service usage examples
β β βββ redux-concepts.tsx # Redux-like state management
β β βββ api-examples.tsx # API service usage examples
β β βββ index.ts # Examples exports
β β βββ CODING_GUIDELINES.md # Project coding standards
β βββ modules/ # Feature-based modules (future use)
βββ public/ # Public assets
βββ .husky/ # Git hooks for quality assurance
βββ .vscode/ # VS Code workspace settings
βββ package.json # Dependencies and scripts
βββ vite.config.ts # Vite configuration (optimized)
βββ tsconfig.app.json # TypeScript config (performance optimized)
βββ vitest.config.ts # Vitest configuration
βββ env.example # Environment variables template
βββ README.md # This file
- Maximum 200 lines per file (preferably 150-180 lines)
- Single responsibility - each file demonstrates one concept
- Clean imports - minimal dependencies
- Clear naming - descriptive file names
- Examples folder - contains focused, reusable example components
The project follows a consistent naming convention for different file types:
- Components:
.component.ts(e.g.,login.component.ts,dashboard.component.ts) - Services:
.service.ts(e.g.,auth.service.ts,patient.service.ts) - Hooks:
.hook.ts(e.g.,auth.hook.ts,patient.hook.ts) - Types:
.types.ts(e.g.,auth.types.ts,patient.types.ts) - Reducers:
.reducer.ts(e.g.,auth.reducer.ts,patient.reducer.ts) - Utilities:
.util.ts(e.g.,storage.util.ts,validation.util.ts) - Constants:
.constant.ts(e.g.,api.constant.ts,routes.constant.ts)
Each module follows a consistent structure and can include sub-modules for complex features:
modules/
βββ [feature-name]/ # Main feature module
β βββ [feature-name].component.ts # Main component
β βββ [feature-name].service.ts # Business logic
β βββ [feature-name].hook.ts # Custom hooks
β βββ [feature-name].types.ts # Type definitions
β βββ [feature-name].constant.ts # Module constants
β βββ [feature-name].util.ts # Module utilities
β βββ [feature-name].test.ts # Module tests
β βββ [sub-feature]/ # Sub-module for complex features
β βββ [sub-feature].component.ts # Sub-feature component
β βββ [sub-feature].service.ts # Sub-feature service
β βββ [sub-feature].hook.ts # Sub-feature hooks
β βββ [sub-feature].types.ts # Sub-feature types
βββ [another-feature]/ # Another main feature
βββ [another-feature].component.ts
βββ [another-feature].service.ts
βββ [another-feature].types.ts
Example Structure:
modules/
βββ auth/ # Authentication module
β βββ auth.component.ts # Main auth component
β βββ auth.service.ts # Auth service
β βββ auth.hook.ts # Auth hooks
β βββ auth.types.ts # Auth types
β βββ login/ # Login sub-module
β β βββ login.component.ts # Login component
β β βββ login.service.ts # Login service
β β βββ login.types.ts # Login types
β βββ register/ # Register sub-module
β βββ register.component.ts # Register component
β βββ register.service.ts # Register service
βββ patients/ # Patients module
βββ patients.component.ts # Main patients component
βββ patients.service.ts # Patients service
βββ patients.types.ts # Patients types
βββ list/ # Patient list sub-module
β βββ patient-list.component.ts # List component
β βββ patient-list.hook.ts # List hooks
βββ details/ # Patient details sub-module
βββ patient-details.component.ts # Details component
βββ patient-details.service.ts # Details service
- Target: ES2020 for modern browsers
- Minification: ESBuild with aggressive optimization
- Code Splitting: Vendor chunks separated
- Source Maps: Disabled in production
- TypeScript: Incremental builds with strict mode
- Bundle Analysis: Visual reports with
yarn analyze
- Statements: 100%
- Branches: 100%
- Functions: 100%
- Lines: 100%
# Run all tests with coverage
yarn test:coverage
# Interactive testing
yarn test:ui
# Watch mode for development
yarn test:watch- Unit Tests: Component and utility testing
- Integration Tests: API and state management
- E2E Tests: [Future implementation]
- No Console: Prevents console.log in production
- TypeScript Strict: Full type safety
- React Best Practices: Hooks and component rules
- Prettier Integration: Consistent formatting
Always use the utility functions and services provided by the project. This includes but is not limited to:
- localStorage/sessionStorage - Use storage utilities
- fetch/XMLHttpRequest - Use HTTP service
- cookies - Use cookie utilities
- IndexedDB - Use database utilities
- WebSocket - Use WebSocket service
- File API - Use file handling utilities
- Geolocation API - Use location service
- Notification API - Use notification service
Storage Management Example:
Always use the storage utility functions from src/utils/storage.ts:
// β WRONG - Don't do this
localStorage.setItem('auth_token', token);
const token = localStorage.getItem('auth_token');
sessionStorage.setItem('user_data', JSON.stringify(user));
// β
CORRECT - Use storage utility
import { storage } from '../utils/storage';
storage.setAuthToken(token);
const token = storage.getAuthToken();
storage.setUserData(user);HTTP Requests Example:
// β WRONG - Don't do this
fetch('/api/users')
.then(response => response.json())
.then(data => console.log(data));
// β
CORRECT - Use HTTP service
import { useHttp } from '../hooks/useHttp';
const { get, data, loading, error } = useHttp();
await get('/api/users');Available Storage Functions:
storage.getAuthToken()- Get authentication tokenstorage.setAuthToken(token)- Set authentication tokenstorage.clearAuthToken()- Clear all auth tokensstorage.get(key)- Generic getterstorage.set(key, value)- Generic setterstorage.remove(key)- Remove specific keystorage.clear()- Clear all storagestorage.setUserData(user)- Set user datastorage.getUserData()- Get user data
- Semi: Always
- Single Quotes: Yes
- Tab Width: 2 spaces
- Print Width: 80 characters
- Trailing Comma: ES5
- Memo: Used for expensive components
- useCallback: Prevents unnecessary re-renders
- Bundle Analysis: Regular bundle size monitoring
Since this app is for health workers who may use tablets and mobile devices:
- Responsive Design: Mobile-first approach with progressive enhancement
- Touch-Friendly: Minimum 44px touch targets for buttons and interactive elements
- Gesture Support: Swipe gestures for navigation and actions
- Fast Loading: Optimized for slower network conditions in rural areas
The project includes a centralized HTTP service with custom hooks for API calls:
HTTP Service (src/services/http.ts):
- Axios-based with interceptors
- Automatic auth token handling
- Error handling for 401 responses
- TypeScript support
Custom Hooks (src/hooks/useHttp.ts):
useHttp<T>()- General HTTP operations with loading/error states- Built-in state management for requests
- Type-safe API calls
API Service (src/services/api.ts):
- Predefined endpoints for common operations
- Simple function-based approach
- No complex class hierarchies
Usage Example:
import { useHttp } from '../hooks/useHttp';
import { apiService } from '../services/api';
function MyComponent() {
const { get, data, loading, error } = useHttp();
const fetchData = async () => {
await get('/api/endpoint');
};
// Or use predefined API functions
const handleLogin = async () => {
await apiService.login({ email, password });
};
}- Development: Hot Module Replacement, Bundle Analyzer, TypeScript checking
- Production: Bundle analysis, performance metrics, error tracking (Sentry)
- Quality: ESLint + Prettier + Husky pre-commit hooks
Our project follows a 4-branch strategy with clear separation of concerns:
main (production)
β
staging (pre-production)
β
qa (quality assurance)
β
dev (development)
main- Production-ready code, stable releases onlystaging- Pre-production environment, final testing before productionqa- Quality assurance branch, testing and validationdev- Development branch, anyone can push for testing
-
Development Flow:
- Devs cut branches from
qafor development - Anyone can push directly to
devfor testing devis used for development server testing
- Devs cut branches from
-
QA Process:
- Feature branches are merged to
devfor dev server testing - Same feature branch is then merged to
qafor QA testing - CRITICAL:
devbranch NEVER merges directly intoqa - Only individual feature branches merge to
qa
- Feature branches are merged to
-
Deployment Flow:
qaβstagingβmain(sequential promotion)- CRITICAL:
devcan NEVER merge directly intoqa - All production deployments must go through the proper QA process
Follow these naming patterns for all feature branches:
feature/<PROJECT_SHORT_CODE>_<feature-name>
feature/<feature-name> # For general features
Examples:
feature/NAS_patient-registration# for example: If it's NAS specificfeature/dashboard-patient-listfeature/auth-login-flowfeature/reports-export
fix/<fix-details-in-short-n-specific>
Examples:
fix/login-validation-errorfix/patient-search-performancefix/mobile-responsive-issues
hotfix/<fix-details-in-short-n-specific>
Examples:
hotfix/critical-security-patchhotfix/production-crash-fixhotfix/urgent-data-loss-prevention
patch/<patch-details>
Examples:
patch/update-dependenciespatch/performance-optimizationpatch/accessibility-improvements
improvements/<PROJECT_SHORT_CODE>_<improvement-details>
improvements/<improvement-details> # For general improvements
Examples:
improvements/patient-ui-uximprovements/dashboard-performanceimprovements/mobile-navigation
# 1. Devs cut branch from QA for development
git checkout qa
git pull origin qa
git checkout -b feature/patient-registration
# 2. Develop on the branch
# ... make changes ...
git add .
git commit -m "feat: implement patient registration"
git push origin feature/patient-registration
# 3. Merge branch to dev for testing on dev server
git checkout dev
git merge feature/patient-registration
git push origin dev
# ... test on dev server ...
# 4. Merge same branch to qa for QA testing (NOT dev to qa!)
git checkout qa
git merge feature/patient-registration
git push origin qa
# ... QA testing the ticket ...
# 5. Once QA approved, merge qa branch to staging
git checkout staging
git merge qa
git push origin staging
# ... staging testing ...
# 6. Finally, merge staging to main for production
git checkout main
git merge staging
git push origin main# 1. Start from main (production issue)
git checkout main
git pull origin main
# 2. Create hotfix branch
git checkout -b hotfix/critical-security-patch
# 3. Fix the issue
# ... make changes ...
# 4. Test and merge to main
git checkout main
git merge hotfix/critical-security-patch
git push origin main
# 5. Also merge to dev, qa and staging to keep them updated
git checkout dev
git merge hotfix/critical-security-patch
git push origin dev
git checkout qa
git merge hotfix/critical-security-patch
git push origin qa
git checkout staging
git merge hotfix/critical-security-patch
git push origin stagingmain: Requires pull request, code review, passing tests, and can only be merged by code owners or repo adminsstaging: Requires pull request, passing tests, and can only be merged by code owners or repo adminsqa: Requires pull request, passing tests, and can only be merged by code owners or repo adminsdev: No restrictions (anyone can push)
β οΈ NEVER mergedevdirectly intoqa- β
Always create feature branches from
dev - β
QA must create branches from
devfor testing - β Use descriptive branch names following the conventions
- β Delete feature branches after merging
- β Keep branch names short but descriptive
- Code Quality: 100% test coverage required
- Performance: Bundle size limits enforced
- Type Safety: Strict TypeScript configuration
- Formatting: Prettier + ESLint auto-fix
- Pre-commit: All checks run automatically via Husky
- Branch Strategy: Follow the GitHub branch strategy outlined above
Before deploying to production, ensure:
- Environment variables configured
- Build optimization enabled
- Performance monitoring active
- Bundle size within limits
- All tests passing (100% coverage)
- Pre-commit checks passing
# Production build
yarn build
# Bundle analysis (generates dist/stats.html)
yarn analyze
# Verify bundle size
ls -la dist/assets/# Dependency security audit
yarn audit
# Check for known vulnerabilities
npm audit
# Review environment variables
grep -r "VITE_" .env*
# Verify no hardcoded secrets
grep -r "password\|secret\|key" src/ --exclude="*.test.*"For technical support or questions, please contact the webapp team lead.
Built with β€οΈ and β for healthcare workers