VaxTrust is a vaccine transparency and safety verification platform built with React. The frontend provides an intuitive interface for users to scan vaccine batch QR codes, view safety scores, and access aggregated vaccine safety data from AEFI (Adverse Events Following Immunization) reports.
Current Status: Frontend is fully functional with static data (no backend required). Ready for backend integration when API server is implemented.
React 18.2.0
- Modern React with Hooks API (useState, useEffect)
- Functional components throughout
- StrictMode enabled for development checks
React Router DOM 6.20.0
- Client-side routing with declarative navigation
- BrowserRouter for clean URLs
- Programmatic navigation with useNavigate hook
Create React App 5.0.1
- Zero-configuration build setup
- Development server with hot reload
- Production optimization and bundling
- Jest testing framework integration
- ESLint configuration
Remix Icon 4.2.0
- Icon library loaded via CDN
- Consistent iconography across UI
- No additional bundle size impact
Google Fonts (Inter)
- Professional typography
- Variable font weights (300-700)
- Optimized for web performance
Static JSON Data Store (Current Implementation)
- No backend API required for demo/testing
- All data served from
/public/data/directory - Three primary data sources:
batches.json- Vaccine batch information (~10 batches with full metadata)trust-scores.json- Aggregated safety scores for all vaccine typesaefi-data.json- Adverse event data per batch with symptoms and trust scores
- In-memory caching for performance (module-level cache variables)
- localStorage for user-submitted reports (demo mode only)
Data File Structures:
batches.json:
[
{
"batch_id": "COV_KA_202302_00001",
"vaccine_name": "COVAXIN",
"vaccine_full_name": "Inactivated COVID-19 vaccine (Bharat Biotech)",
"manufacturer": "Bharat Biotech International Limited",
"batch_number": "00001",
"state": "Karnataka",
"allocated_to": "Karnataka State Immunization Officer",
"manufacturing_date": "2021-11-07",
"expiry_date": "2022-10-27",
"doses_in_batch": 1000,
"received_date": "2022-06-20",
"vaccine_cold_chain": "2-8°C",
"storage_location": "Karnataka Cold Storage - Unit 4"
}
]aefi-data.json:
{
"aefi_by_batch": {
"COV_KA_202302_00001": [
{
"symptom": "fever",
"count": 15,
"severity_breakdown": { "mild": 10, "moderate": 4, "severe": 1 }
}
]
},
"trust_by_batch": {
"COV_KA_202302_00001": {
"score": 0.87,
"total_cases": 31,
"causal_cases": 4,
"classification_breakdown": { "A1": 2, "A2": 1, "A4": 1, "B1": 4, "C": 23 }
}
},
"outcome_by_batch": {
"COV_KA_202302_00001": {
"recovered": 20,
"hospitalized": 8,
"ongoing": 3
}
}
}trust-scores.json:
{
"generated_at": "2025-12-25T00:00:00Z",
"vaccines": [
{
"vaccine_name": "COVISHIELD",
"vaccine_full_name": "Oxford/AstraZeneca (Manufactured by SII)",
"manufacturer": "Serum Institute of India",
"total_batches": 847,
"trust_score": {
"score": 0.92,
"total_cases": 198,
"causal_cases": 16,
"deaths": 31,
"hospitalized": 92,
"classification_breakdown": { "A1": 8, "A2": 3, "A3": 2, "A4": 3, "B1": 24, "B2": 18, "C": 140 }
},
"common_side_effects": [
{ "symptom": "fever", "count": 45 },
{ "symptom": "headache", "count": 38 }
]
} (from ScanPage via App.js state)
**Layout:**
- Two-column responsive layout
- Left column: Trust score circle with visual ring indicator
- Right column: Batch details, side effects, outcomes, causality analysis
**Data Display:**
- **Trust Score Circle:** Animated ring showing score percentage with color coding
- **Trust Badge:** Safety classification label (High Safety/Moderate Safety/Review Recommended)
- **Trust Stats:** Total reports and causal cases count
- **Vaccine Details Card:** All batch metadata (vaccine name, manufacturer, batch ID, state, expiry, storage)
- **Reported Side Effects Card:** Common symptoms with count badges and severity breakdown
- **Outcome Summary Card:** Recovery status distribution (recovered, hospitalized, ongoing, death)
- **Causality Analysis Card:** WHO classification breakdown (A1-A4, B1-B2, C categories)
**Trust Score Color Logic:**
```javascript
>= 85% = High Safety (Green #4A9B7F)
>= 70% = Moderate Safety (Orange #C4944A)
< 70% = Review Recommended (Red #C45A5A)Visual Elements:
- Circular progress indicator with animated border
- Color-coded badges and icons
- Responsive info rows with labels and values
- Tag-based symptom display
- Icon indicators for each data type
Actions:
- Back to Scan button (desktop and mobile)
- Navigate to Dashboard
- Report Symptoms (navigates to FeedbackPage with batch contextning interface │ │ ├── ResultPage.js # Batch safety results │ │ ├── DashboardPage.js # Vaccine overview dashboard │ │ └── FeedbackPage.js # Symptom reporting │ └── services/ │ └── api.js # Data fetching service layer └── package.json # Dependencies and scripts
## Component Architecture
### App.js (Root Component)
**Purpose:** Application shell with routing configuration
**State Management:**
- Props:**
- `batchData` - Batch context from scanning (provides batch_id)
**State:**
- `selectedSymptoms` - Array of selected symptom names
- `severity` - "mild", "moderate", or "severe"
- `onsetDays` - Number of days since vaccination
- `notes` - Optional user comments
- `loading` - Submission status
- `submitted` - Success state
- `error` - Error messages
**Symptom Options (10 predefined):**
```javascript
const SYMPTOM_OPTIONS = [
{ name: 'Fever', icon: 'ri-temp-hot-line' },
{ name: 'Headache', icon: 'ri-mental-health-line' },
{ name: 'Fatigue', icon: 'ri-rest-time-line' },
{ name: 'Muscle Pain', icon: 'ri-walk-line' },
{ name: 'Injection Site Pain', icon: 'ri-syringe-line' },
{ name: 'Nausea', icon: 'ri-emotion-sad-line' },
{ name: 'Chills', icon: 'ri-temp-cold-line' },
{ name: 'Joint Pain', icon: 'ri-body-scan-line' },
{ name: 'Dizziness', icon: 'ri-loader-line' },
{ name: 'Other', icon: 'ri-more-line' }
];
Features:
- Requirement Check: Redirects to scan page if no batch context available
- Multi-select Symptoms: Clickable cards with toggle selection
- Severity Selection: Three-button radio group (Mild/Moderate/Severe)
- Onset Days Input: Optional numeric field for timing
- Notes Field: Optional textarea for additional details
- Validation: Client-side checks for required fields
- Success State: Confirmation message with batch ID reference
- localStorage Persistence: Reports stored locally with timestamp and ID (
RPT_<timestamp>)
Form Structure:
{
batch_id: "COV_KA_202302_00001",
symptoms: ["Fever", "Headache"],
severity: "mild",
onset_days: 2, // optional
notes: "..." // optional
}User Flow:
- User arrives from ResultPage with batch context
- Selects symptoms (minimum 1 required)
- Chooses severity level (required)
- Optionally adds onset days and notes
- Submits form with validation
- Sees success confirmation
- Can report another or return homes)
/dashboard- DashboardPage (aggregate data)/feedback- FeedbackPage (symptom r (demo mode)- Adds timestamp and auto-generated ID
- Parameters:
{ batch_id, symptoms, severity, onset_days?, notes? } - Returns:
{ success: true, message, report_id } - Report ID format:
RPT_<timestamp>(e.g.,RPT_1735123045123) - Future: all available batch IDs from batches.json
- Used for quick testing on ScanPage
- Displays first 4 batches as clickable demo buttons
- Returns:
{ sample_batches: ["COV_AN_202203_00000", ...] }
healthCheck()
- Always returns healthy status in static mode
- Returns:
{ status: "healthy", mode: "static", message: "VaxTrust running in static mode" } - Future: Will check backend API status when integrateder entry point for batch verification
State:
manualInput- User-entered batch IDloading- Request status indicatorerror- Error message displaysampleBatches- Pre-loaded example batches
Features:
- QR code scanner interface (UI only, camera integration pending)
- Manual batch ID input with validation
- Quick-access sample batch buttons
- Real-time error handling
- Navigation to dashboard
User Flow:
- User scans QR code OR enters batch ID manually
- System validates input
- Fetches batch data via API service
- Navigates to ResultPage with data
- Shows appropriate error if batch not found
Purpose: Display comprehensive batch safety information
Props:
batchData- Complete batch and trust score data
Data Display:
- Trust score with visual indicator (0-100%)
- Safety classification (High/Moderate/Low)
- Batch details (manufacturer, expiry, state)
- Common side effects with frequency
- Outcome summary statistics
- AEFI classification breakdown
Trust Score Logic:
>= 85% = High Safety (Green)
>= 70% = Moderate Safety (Orange)
< 70% = Review Recommended (Red)
Actions:
- Navigate back to scan page
- Navigate to dashboard
- Report symptoms (navigates to feedback page)
Purpose: Aggregate view of all vaccine safety data
State:
data- Complete trust scores datasetloading- Data loading indicatorerror- Error state handling
Features:
- Overview of all COVID-19 vaccines
- Trust scores by vaccine type
- Total doses administered
- Aggregate AEFI statistics
- Batch count per vaccine
- Color-coded safety indicators
Data Loading:
- Fetches on component mount
- Shows loading spinner
- Error state with retry option
- Responsive card layout
Purpose: Anonymous symptom reporting interface
State:
- Form data for symptom submission
- Validation state
- Submission status
Features:
- Anonymous reporting (no personal data)
- Symptom selection interface
- Severity rating
- Date of vaccination
- Batch ID pre-filled from context
- localStorage persistence (demo mode)
Purpose: Centralized data access layer
Architecture:
- Singleton caching pattern
- Asynchronous data loading
- Error handling with structured responses
- No external API dependencies
Functions:
loadBatches()
- Loads batch data from static JSON
- Returns cached data on subsequent calls
- Source:
/data/batches.json
loadTrustScores()
- Loads aggregate trust score data
- Implements caching
- Source:
/data/trust-scores.json
loadAefiData()
- Loads adverse event data
- Caches for performance
- Source:
/data/aefi-data.json
getBatchDetails(batchId)
- Primary function for batch lookup
- Parameters:
batchId(string) - Returns: Complete batch object with:
- Batch metadata
- Trust score and statistics
- Common side effects
- Outcome summary
- Throws: 404 error if batch not found
getTrustScores()
- Returns all vaccine trust scores
- Used by dashboard for overview
- Includes aggregated statistics
reportSymptom(report)
- Stores symptom report in localStorage
- Demo implementation (no backend)
- Returns confirmation object
getSampleBatches()
- Returns example batch IDs
- Used for quick testing
- Helpful for new users
Global Styles (index.css):
- CSS custom properties for theming
- Mobile-first responsive design
- Flexbox and Grid layouts
- No CSS framework dependencies
Design System:
Colors:
- Primary: Teal/Cyan palette
- Success: Green (#059669)
- Warning: Orange (#d97706)
- Danger: Red (#dc2626)
- Neutral: Grays for text and backgrounds
Typography:
- Font Family: Inter (Google Fonts)
- Base Size: 16px
- Scale: Consistent sizing hierarchy
- Weights: 400 (regular), 500 (medium), 600 (semibold)
Components:
- Cards with subtle shadows
- Rounded corners (8-16px border radius)
- Icon integration with Remix Icon
- Button variants (primary, secondary, outline)
- Form inputs with focus states
- Loading states and spinners
- Alert/notification patterns
Responsive Design:
- Mobile-first breakpoints
- Flexible grid layouts
- Touch-friendly tap targets (44px minimum)
- Viewport meta tag for proper scaling
Semantic, component-
When the backend is ready, update services/api.js:
- Change
fetch()calls from/data/*.jsonto API endpoints - Update base URL:
const API_BASE_URL = 'http://localhost:5000/api'; - Modify functions to use REST endpoints:
export const getBatchDetails = async (batchId) => { const response = await fetch(`${API_BASE_URL}/batch/${batchId}`); if (!response.ok) { const error = new Error('Batch not found'); error.response = { status: response.status }; throw error; } return response.json(); };
- Remove localStorage logic from
reportSymptom() - Add error handling for network failures
- Consider adding request interceptors for auth (if needed later)based naming:
.card
.card-header
.card-title
.card-subtitle
.btn
.btn-primary
.btn-full
.trust-score-card
.trust-score-circle
.info-list
.info-row
User Action (Scan Page)
↓
getBatchDetails(batchId)
↓
Fetch from Static JSON
↓
Process & Combine Data
↓
Update Parent State (App.js)
↓
Navigate to Result Page
↓
Display Results
Initial Load:
- First API call loads JSON from
/data/directory - Data stored in module-level cache variables
- Subsequent calls return cached data instantly
Benefits:
- Reduced network requests
- Faster page transitions
- Consistent data across views
- No cache invalidation needed (static data)
Network Errors:
- Graceful degradation with user-friendly messages
- Retry mechanisms where appropriate
- Empty states for missing data
Validation Errors:
- Client-side input validation
- Real-time error messages
- Clear error descriptions
404 Handling:
- Specific message for batch not found
- Guidance to check batch ID
- Navigation back to scan page
Start Development Server:
npm start- Launches on http://localhost:3000
- Hot module reloading enabled
- Opens browser automatically
Build Production Bundle:
npm build- Creates optimized production build
- Output to
/builddirectory - Minified and tree-shaken
- Ready for deployment
Run Tests:
npm test- Runs Jest test suite
- Interactive watch mode
- Coverage reports available
Eject Configuration:
npm run eject- One-wment API calls after the backend is built (currently using static JSON)
- Add request/response interceptors for better error handling
- Implement retry logic for failed requests
- Add loading skeletons instead of spinners
- Exposes webpack/babel configuration
- Not recommended unless necessary
Prerequisites:
- Node.js 14+ (recommended: 18+)
- npm 6+ or yarn
- Modern browser (Chrome, Firefox, Safari, Edge)
Installation:
cd frontend
npm installEnvironment Configuration:
- No environment variables required
- Data served from
/public/data/directory homepage: "."in package.json for flexible deployment
- Create component in
/src/pages/NewPage.js - Import necessary hooks and services
- Add route in
App.js:<Route path="/new-page" element={<NewPage />} />
- Add navigation button where needed
- Place JSON file in
/public/data/ - Create loader function in
api.js:let newDataCache = null; const loadNewData = async () => { if (newDataCache) return newDataCache; const response = await fetch('/data/new-data.json'); newDataCache = await response.json(); return newDataCache; };
- Export public API function
- Use in components
- Follow existing class naming patterns
- Use existing color variables
- Ensure mobile responsiveness
- Add styles to
index.css - Test on multiple screen sizes
Framework: Jest (via Create React App)
Test Types:
- Unit tests for utility functions
- Component tests with React Testing Library
- Integration tests for user flows
Running Tests:
npm test # Watch mode
npm test -- --coverage # With coverage report
npm test -- --watchAll=false # Single runPriority Areas:
- API service functions (getBatchDetails, getTrustScores)
- Form validation logic
- Error handling paths
- Navigation flows
- Trust score calculations
Recommended Platforms:
- Vercel (zero-config React deployment)
- Netlify (drag-and-drop or CLI)
- GitHub Pages
- AWS S3 + CloudFront
- Firebase Hosting
npm run buildOutput:
- Optimized bundle in
/build/ - Code splitting for better performance
- Minified CSS and JS
- Asset fingerprinting for cache busting
- Run production build
- Test build locally (
npx serve -s build) - Verify all routes work
- Check data loading from
/data/directory - Test on mobile devices
- Verify browser compatibility
- Check console for errors
- Test edge cases (invalid batch IDs, etc.)
Production:
- Chrome/Edge (last 2 versions)
- Firefox (last 2 versions)
- Safari (last 2 versions)
- Mobile Safari (iOS 12+)
- Chrome Mobile (Android 8+)
Development:
- Latest Chrome
- Latest Firefox
- Latest Safari
- ES6+ JavaScript support
- Fetch API
- LocalStorage
- CSS Grid and Flexbox
- CSS Custom Properties
Code Splitting:
- React Router automatically splits by route
- Lazy loading can be added for larger components
Caching:
- In-memory data caching
- Browser HTTP caching for static assets
- Service Worker potential (not yet implemented)
Asset Optimization:
- Minified JavaScript and CSS
- Optimized images (if any added)
- Font loading optimization
- Implement service worker for offline support
- Add image lazy loading
- Optimize bundle size with dynamic imports
- Add skeleton screens for better perceived performance
- Implement virtual scrolling for large lists
- Impletement API calls after the backend is built as currently the values are hardcoded
ARIA Considerations:
- Semantic HTML elements
- Icon-only buttons should include aria-labels
- Form inputs should have proper labels
- Loading states should be announced
Keyboard Navigation:
- All interactive elements keyboard accessible
- Logical tab order
- Focus visible states
- All images have alt text
- Form inputs have labels
- Color contrast meets WCAG AA standards
- Focus indicators visible
- Screen reader testing
- Keyboard-only navigation testing
Data Privacy:
- No personal data collection
- Anonymous symptom reporting
- No authentication required
- LocalStorage for demo data only
Content Security:
- React's built-in XSS protection
- No dangerouslySetInnerHTML usage
- Input sanitization for batch IDs
Network Security:
- HTTPS recommended for deployment
- No sensitive data transmission
- Static data only (no API keys)
Cause: Invalid or non-existent batch ID
Solution:
- Check batch ID format
- Verify data exists in
batches.json - Use sample batches for testing
Cause: Missing or malformed JSON files
Solution:
- Verify JSON files exist in
/public/data/ - Check JSON syntax validity
- Check browser console for fetch errors
Cause: Server not configured for client-side routing
Solution:
- Configure server to serve index.html for all routes
- For static hosts, add
_redirectsorvercel.jsonconfig - Use HashRouter as fallback
Cause: CSS import or build issues
Solution:
- Verify
index.cssis imported inindex.js - Check for CSS syntax errors
- Clear browser cache
- Rebuild the application
Current State:
- Frontend is fully functional with static JSON data
- No API calls to backend server yet
- All data served from
/public/data/directory - User reports stored in localStorage (temporary)
Expected Backend Endpoints (see API_CONTRACT.md for full details):
-
GET /api/batch/:batch_id
- Returns: Batch details with trust score, side effects, and outcome summary
- Frontend expects exact structure as shown in API_CONTRACT.md
- Used by: ScanPage → ResultPage flow
-
GET /api/trust-scores
- Returns: Array of all vaccines with aggregated trust scores
- Frontend expects exact structure as shown in API_CONTRACT.md
- Used by: DashboardPage
-
POST /api/report-symptom
- Accepts:
{ batch_id, symptoms[], severity, onset_days?, notes? } - Returns:
{ success: true, report_id, message } - Used by: FeedbackPage
- Accepts:
-
GET /api/batches
- Returns:
{ sample_batches: [...] }(for demo/testing) - Used by: ScanPage for quick access buttons
- Returns:
-
GET /api/health
- Returns: Server health status
- Optional but recommended
Data Structure Requirements:
The backend MUST return data in the exact structure the frontend expects. Key fields:
Batch Details Response:
{
batch: {
batch_id: string,
vaccine_name: string,
vaccine_full_name: string,
manufacturer: string,
state: string,
expiry_date: string (YYYY-MM-DD),
manufacturing_date: string,
vaccine_cold_chain: string,
storage_location: string,
doses_in_batch: number,
batch_number: string,
allocated_to: string,
received_date: string
},
trust_score: {
score: number (0-1),
total_cases: number,
causal_cases: number,
classification_breakdown: {
"A1": number,
"A2": number,
"A3": number,
"A4": number,
"B1": number,
"B2": number,
"C": number
}
},
common_side_effects: [
{
symptom: string (lowercase, underscore_separated),
count: number,
severity_breakdown: {
mild: number,
moderate: number,
severe: number
}
}
],
outcome_summary: {
recovered: number,
hospitalized: number,
ongoing: number,
death: number
}
}Trust Scores Response:
{
generated_at: string (ISO date),
vaccines: [
{
vaccine_name: string,
vaccine_full_name: string,
manufacturer: string,
total_batches: number,
trust_score: { /* same structure as above */ },
common_side_effects: [ /* same structure as above */ ]
}
]
}Critical Notes for Backend:
- Symptom names should be lowercase with underscores (e.g., "injection_site_pain")
- Trust scores are decimals (0-1), frontend converts to percentage
- Classification breakdown includes all WHO categories (A1-A4, B1-B2, C)
- Dates should be ISO strings or YYYY-MM-DD format
- Handle 404 errors properly for invalid batch IDs
- CORS must be enabled for development (frontend runs on :3000, backend on :5000)
Frontend Changes Needed When Backend is Ready:
- Update
services/api.jsbase URL - Change
fetch('/data/*.json')tofetch('http://localhost:5000/api/...') - Remove localStorage logic from reportSymptom
- Add proper error handling for network failures
- Optional: Add loading states during API calls
QR Code Integration:
- Implement actual QR code scanning
- Camera permission handling
- QR code parsing library integration
Enhanced Reporting:
- More detailed symptom form
- File upload for medical documents
- Follow-up tracking
Data Visualization:
- Interactive charts (Chart.js or Recharts)
- Time-series AEFI trends
- Geographic distribution maps
User Experience:
- Dark mode toggle
- Language internationalization (i18n)
- Progressive Web App (PWA) features
- Offline support with Service Workers
Backend Integration:
- Replace static JSON with REST API
- Real-time data updates
- User authentication (optional)
- Report aggregation and analytics
JavaScript:
- Use functional components with hooks
- Avoid class components
- Destructure props and state
- Use async/await for promises
- Add JSDoc comments for complex functions
Naming Conventions:
- Components: PascalCase (UserProfile.js)
- Functions: camelCase (getUserData)
- Constants: UPPER_SNAKE_CASE (API_BASE_URL)
- CSS classes: kebab-case (user-profile-card)
File Organization:
- One component per file
- Related components in same directory
- Tests alongside components (ComponentName.test.js)
- Shared utilities in
/utils/directory
- Create feature branch from main
- Implement changes with clear commits
- Test thoroughly across browsers
- Update documentation if needed
- Submit PR with description of changes
- Address review feedback
- Merge after approval
- Code follows style guidelines
- No console.log statements in production code
- Error handling implemented
- Mobile responsive
- Accessibility considered
- Comments added for complex logic
- No unnecessary dependencies added
- React Documentation: https://react.dev/
- React Router: https://reactrouter.com/
- Create React App: https://create-react-app.dev/
- Remix Icon: https://remixicon.com/
- Color Palette: Tailwind CSS colors as reference
- Typography: Inter font family
- Icons: Remix Icon set
- API_CONTRACT.md - Backend API specification
- README.md - Project overview
- MVP_REPORT.txt - MVP features
For questions, issues, or contributions:
- Review this documentation thoroughly
- Check existing issues in version control
- Consult API_CONTRACT.md for data structure
- Reference code comments in components
v1.0.0 (Current)
- Initial release with core features
- QR code scanning interface (UI)
- Batch verification system
- Dashboard with aggregate data
- Anonymous symptom reporting
- Static JSON data architecture
- Mobile-responsive design