chore: Remove development files from git tracking and update .gitignore
Some checks failed
ParentFlow CI/CD Pipeline / Backend Tests (push) Has been cancelled
ParentFlow CI/CD Pipeline / Frontend Tests (push) Has been cancelled
ParentFlow CI/CD Pipeline / Security Scanning (push) Has been cancelled
ParentFlow CI/CD Pipeline / Build Docker Images (map[context:maternal-app/maternal-app-backend dockerfile:Dockerfile.production name:backend]) (push) Has been cancelled
ParentFlow CI/CD Pipeline / Build Docker Images (map[context:maternal-web dockerfile:Dockerfile.production name:frontend]) (push) Has been cancelled
ParentFlow CI/CD Pipeline / Deploy to Development (push) Has been cancelled
ParentFlow CI/CD Pipeline / Deploy to Production (push) Has been cancelled
CI/CD Pipeline / Lint and Test (push) Has been cancelled
CI/CD Pipeline / E2E Tests (push) Has been cancelled
CI/CD Pipeline / Build Application (push) Has been cancelled

Removed from git tracking:
- docs/ folder (all planning and implementation documentation)
- CLAUDE.md (AI assistant instructions)
- start-dev.sh and stop-dev.sh (development scripts)

Updated .gitignore to exclude:
- Documentation and planning files (docs/, CLAUDE.md)
- Development scripts and logs (*.dev.log, start-dev.sh, stop-dev.sh)
- Development environment folders (.dev/, dev-data/)
- Temporary development files (*.tmp, *.temp, .scratch/)

These files remain available locally for development but won't be committed to the repository.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Andrei
2025-10-08 11:10:28 +00:00
parent 762086f6ab
commit 4e9fe52106
52 changed files with 19 additions and 30734 deletions

19
.gitignore vendored
View File

@@ -83,3 +83,22 @@ maternal-web/.cache/
# package-lock.json # package-lock.json
# yarn.lock # yarn.lock
# pnpm-lock.yaml # pnpm-lock.yaml
# Documentation and planning (development only)
docs/
CLAUDE.md
# Development scripts and logs
start-dev.sh
stop-dev.sh
*.dev.log
/tmp/*.log
# Development environment
.dev/
dev-data/
# Temporary development files
*.tmp
*.temp
.scratch/

343
CLAUDE.md
View File

@@ -1,343 +0,0 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
This is a planning and documentation repository for an **AI-powered maternal organization app** designed to help parents manage childcare for children aged 0-6 years. The app focuses on reducing mental load through intelligent tracking, real-time family sync, and AI-powered parenting support.
**Current Status**: Documentation phase - no code implementation yet. All source files are comprehensive planning documents.
## Core Technology Stack
### Mobile Application
- **Framework**: React Native with Expo
- **State Management**: Redux Toolkit with offline-first architecture
- **Local Database**: SQLite with TypeORM
- **Navigation**: React Navigation
- **UI Components**: React Native Paper (Material Design)
### Backend Infrastructure
- **Framework**: NestJS (Node.js)
- **API Style**: Hybrid REST + GraphQL + WebSocket
- **Primary Database**: PostgreSQL 15+ (with partitioned activity tables)
- **Document Store**: MongoDB (for AI chat history)
- **Cache/Queue**: Redis
- **Object Storage**: MinIO (S3-compatible)
### AI/ML Services
- **LLM**: OpenAI GPT-4 / Anthropic Claude / Google Gemini APIs
- **Framework**: LangChain for context management
- **Voice Recognition**: OpenAI Whisper
- **Pattern Recognition**: Custom algorithms with TensorFlow.js
### Real-Time Features
- **Sync**: Socket.io for family coordination
- **Push Notifications**: Firebase Cloud Messaging / Expo Notifications
## Architecture Highlights
### State Management Design
- **Normalized state shape** with entities stored in `byId` dictionaries
- **Offline-first** with automatic sync queue and conflict resolution
- **Optimistic updates** for instant UI feedback
- Separate slices: auth, user, family, children, activities, ai, sync, offline, ui, notifications, analytics
### API Architecture
- Base URL: `https://api.{domain}/api/v1`
- GraphQL endpoint for complex queries: `/graphql`
- WebSocket for real-time sync: `wss://api.{domain}/ws`
- **Device fingerprinting** for multi-device auth
- **JWT access tokens** (1h) + refresh tokens with rotation
- Rate limiting: 100 requests/minute per user
### Database Schema Strategy
- **Partitioned tables** for activities (feeding, sleep, diapers) using monthly partitions
- **Audit logging tables** for COPPA/GDPR compliance
- **Performance indexes** on commonly queried fields (childId, createdAt)
- Migration scripts numbered V001-V007+ for sequential deployment
### AI Context Management
- **Token budget**: 4000 tokens max per request
- **Priority weighting system** for context selection:
- Current query: 1.0
- Recent activities (48h): 0.8
- Child profile: 0.7
- Historical patterns: 0.6
- General guidelines: 0.4
- **Safety boundaries**: Medical disclaimer triggers, mental health resources, prompt injection protection
- **Multi-language support**: 5 languages (English, Spanish, French, Portuguese, Chinese)
## Key Documentation Files
### Technical Architecture
- `docs/maternal-app-tech-stack.md` - Complete technology choices with library recommendations
- `docs/maternal-app-implementation-plan.md` - 8-phase development roadmap with deliverables
- `docs/maternal-app-api-spec.md` - REST/GraphQL/WebSocket endpoint specifications
- `docs/maternal-app-db-migrations.md` - Database schema with migration scripts
### AI/ML Integration
- `docs/maternal-app-ai-context.md` - LangChain configuration, prompt templates, safety boundaries
- `docs/maternal-app-voice-processing.md` - Voice input patterns and NLP processing
- `docs/maternal-app-state-management.md` - Redux Toolkit architecture with offline support
### UI/UX Design
- `docs/maternal-app-design-system.md` - Material Design system with warm color palette
- `docs/maternal-app-mvp.md` - MVP feature scope and success metrics
- `docs/maternal-app-testing-strategy.md` - Testing approach (unit, integration, E2E)
### DevOps & Deployment
- `docs/maternal-app-env-config.md` - Environment variables and Docker setup
- `docs/maternal-app-mobile-deployment.md` - iOS/Android build and release process
- `docs/maternal-app-error-logging.md` - Error codes and logging standards
## Implementation Commands (Future)
### Project Setup
```bash
# Frontend - React Native with Expo
npx create-expo-app maternal-app --template
cd maternal-app
npm install @reduxjs/toolkit react-redux redux-persist
npm install react-navigation react-native-paper
npm install @react-native-async-storage/async-storage
npm install react-native-sqlite-storage
# Backend - NestJS
nest new maternal-app-backend
cd maternal-app-backend
npm install @nestjs/typeorm @nestjs/jwt @nestjs/websockets
npm install @nestjs/graphql @apollo/server graphql
npm install pg redis bull socket.io
```
### Development Workflow
```bash
# Frontend development
npm start # Start Expo dev server
npm run ios # Run on iOS simulator
npm run android # Run on Android emulator
npm test # Run Jest unit tests
# Backend development
npm run start:dev # Start NestJS with hot reload
npm run test # Run unit tests
npm run test:e2e # Run integration tests
npm run migration:run # Apply database migrations
# Docker environment
docker-compose up -d # Start PostgreSQL, Redis, MongoDB, MinIO
```
### Testing
```bash
# Unit tests (Jest)
npm test -- --coverage # Run with coverage report
# E2E tests (Detox for mobile)
detox build --configuration ios.sim.debug
detox test --configuration ios.sim.debug
# Backend integration tests
npm run test:e2e
```
### Database Management
```bash
# Run migrations in sequence
npm run migration:run
# Rollback last migration
npm run migration:revert
# Generate new migration
npm run migration:generate -- -n MigrationName
```
## Design Principles
### Mobile UX Requirements
- **One-handed operation**: All critical actions in bottom 60% of screen
- **Interruption-resilient**: Auto-save all inputs, no data loss on app switch
- **Minimum touch targets**: 44x44px (iOS) / 48x48dp (Android)
- **Performance**: 60fps scrolling, <2s load time, skeleton screens for loading states
### Color Palette (Warm, Nurturing)
- Primary: Peach (#FFB5A0), Coral (#FF8B7D), Rose (#FFD4CC)
- Semantic: Sage green (success), Amber (warning), Soft red (error)
- Material Design principles throughout
### Accessibility
- WCAG AA/AAA compliance
- Screen reader support
- High contrast mode
- Text size adjustment
- Multi-language support (5 languages in MVP)
## Security & Compliance
### Authentication Flow
1. Email/phone signup with verification
2. Device fingerprinting on registration
3. JWT access token (1h) + refresh token
4. Biometric login option (Face ID / Touch ID / Fingerprint)
5. Multi-device session management
### Privacy Considerations
- **COPPA compliance**: Age verification, parental consent flows
- **GDPR compliance**: Data export, right to deletion, consent management
- **End-to-end encryption** for sensitive child data
- **Audit tables** tracking all data access and modifications
- **No third-party data sharing** without explicit consent
### Error Handling Standards
- Structured error codes (e.g., `AUTH_DEVICE_NOT_TRUSTED`, `LIMIT_FAMILY_SIZE_EXCEEDED`)
- User-friendly error messages in all 5 languages
- Sentry integration for error tracking
- Audit logging for security events
## MVP Scope (6-8 Weeks)
### Core Features
1. **Tracking**: Feeding, sleep, diapers with voice input
2. **AI Assistant**: 24/7 contextual parenting support using LangChain
3. **Family Sync**: Real-time updates via WebSocket
4. **Pattern Recognition**: Sleep predictions, feeding trends
5. **Analytics**: Daily/weekly summaries, exportable reports
### Success Metrics
- 1,000 downloads in first month
- 60% daily active users
- 70% of users try AI assistant
- <2% crash rate
- 4.0+ app store rating
### Deferred to Post-MVP
- Meal planning
- Financial tracking
- Community forums
- Smart home integration
- School platform integrations
## Code Organization (Planned)
```
/maternal-app (React Native)
/src
/components
/common # Reusable UI components
/tracking # Activity tracking components
/ai # AI chat interface
/screens # Screen components
/services # API clients, device services
/hooks # Custom React hooks
/redux
/slices # Redux Toolkit slices
/locales # i18n translations
/navigation # React Navigation config
/types # TypeScript definitions
/maternal-app-backend (NestJS)
/src
/modules
/auth # Authentication & authorization
/users # User management
/families # Family coordination
/children # Child profiles
/tracking # Activity tracking
/ai # AI/LLM integration
/common
/guards # Auth guards
/interceptors # Request/response transformation
/filters # Exception filters
/database
/entities # TypeORM entities
/migrations # Database migrations
```
## Development Best Practices
### Git Workflow
- Branch naming: `feature/`, `bugfix/`, `hotfix/`
- Commit messages: Conventional commits (feat:, fix:, docs:, test:)
- Pre-commit hooks: ESLint, Prettier, type checking
### Testing Strategy
- **Target**: 80% code coverage
- Unit tests for all services and utilities
- Integration tests for API endpoints
- E2E tests for critical user journeys
- Mock AI responses for predictable testing
### Performance Optimization
- Redis caching for frequent queries
- Database query optimization with indexes
- Image optimization with Sharp
- Code splitting and lazy loading
- Offline-first architecture with sync queue
## Multi-Language Support
### Supported Languages (MVP)
1. English (en-US) - Primary
2. Spanish (es-ES)
3. French (fr-FR)
4. Portuguese (pt-BR)
5. Simplified Chinese (zh-CN)
### Localization Framework
- i18next for string externalization
- react-i18next for React integration
- react-native-localize for device locale detection
- All strings externalized from day 1
- Date/time/number formatting per locale
- AI responses localized per user preference
## Critical Implementation Notes
### Offline-First Architecture
- All core features (tracking) work offline
- Automatic sync queue when connectivity restored
- Conflict resolution strategy: last-write-wins with timestamp comparison
- Optimistic UI updates for instant feedback
### Real-Time Family Sync
- WebSocket connection per device
- Event-driven architecture for activity updates
- Presence indicators (who's online)
- Typing indicators for AI chat
- Connection recovery with exponential backoff
### AI Safety Guardrails
- Medical disclaimer triggers for health concerns
- Crisis hotline integration for mental health
- Rate limiting: 10 AI queries/day (free), unlimited (premium)
- Response moderation and filtering
- Prompt injection protection
### Data Migration Strategy
- Sequential migration scripts (V001, V002, etc.)
- Rollback procedures for each migration
- Data seeding for development/testing
- Backup verification before production migrations
## Future Roadmap Considerations
### Phase 2 (Months 2-3)
- Community features with moderation
- Photo milestone tracking
- Meal planning basics
- Calendar integration (Google, Apple, Outlook)
### Phase 3 (Months 4-6)
- Financial tracking
- Smart home integration (Alexa, Google Home)
- Professional tools for caregivers
- Telemedicine integration
### Scalability Preparations
- Kubernetes deployment for horizontal scaling
- Database sharding strategy for multi-tenancy
- CDN for static assets
- Message queue (RabbitMQ/Kafka) for async processing
- Microservices architecture when needed

View File

@@ -1,641 +0,0 @@
# Localization Implementation Plan
**Created**: October 3, 2025
**Priority**: HIGH (Pre-Launch)
**Estimated Duration**: 2-3 days
## Overview
Implement comprehensive internationalization (i18n) support for the Maternal App with 5 languages and measurement unit preferences.
## Supported Languages
1. **English (en-US)** - Primary/Default
2. **Spanish (es-ES)**
3. **French (fr-FR)**
4. **Portuguese (pt-BR)**
5. **Simplified Chinese (zh-CN)**
## Current Status
### ✅ Already Completed
- Backend multilanguage support for AI responses
- AI safety responses in 5 languages
- MultiLanguageService with language detection
### ❌ To Be Implemented
- Frontend i18next framework
- Translation files for all UI strings
- Language selector in onboarding
- Language selector in settings
- Date/time localization
- Measurement unit preferences (Metric/Imperial)
- Number formatting per locale
---
## Phase 1: Framework Setup
### 1.1 Install Dependencies
**Files**: `package.json`
```bash
npm install i18next react-i18next i18next-browser-languagedetector
npm install date-fns # Already installed, confirm locales
```
**Packages**:
- `i18next` - Core i18n framework
- `react-i18next` - React bindings
- `i18next-browser-languagedetector` - Auto-detect user language
### 1.2 Create i18n Configuration
**File**: `lib/i18n/config.ts` (NEW)
- Initialize i18next
- Configure language detector
- Set up fallback language (en-US)
- Configure interpolation
- Load translation resources
### 1.3 Create i18n Provider
**File**: `components/providers/I18nProvider.tsx` (NEW)
- Wrap app with I18nextProvider
- Initialize i18n on mount
- Handle language loading states
### 1.4 Update Root Layout
**File**: `app/layout.tsx` (MODIFY)
- Add I18nProvider to provider stack
- Set html lang attribute dynamically
---
## Phase 2: Translation Files Structure
### 2.1 Directory Structure
```
locales/
├── en/
│ ├── common.json # Common UI strings (buttons, labels, etc.)
│ ├── auth.json # Authentication pages
│ ├── dashboard.json # Dashboard/home page
│ ├── tracking.json # Activity tracking
│ ├── children.json # Child management
│ ├── family.json # Family management
│ ├── ai.json # AI assistant
│ ├── analytics.json # Analytics/insights
│ ├── settings.json # Settings page
│ ├── onboarding.json # Onboarding flow
│ ├── errors.json # Error messages
│ └── validation.json # Form validation messages
├── es/
│ └── [same structure]
├── fr/
│ └── [same structure]
├── pt/
│ └── [same structure]
└── zh/
└── [same structure]
```
### 2.2 Translation Keys Structure
**Example - common.json**:
```json
{
"nav": {
"dashboard": "Dashboard",
"track": "Track",
"children": "Children",
"family": "Family",
"ai": "AI Assistant",
"analytics": "Analytics",
"settings": "Settings"
},
"buttons": {
"save": "Save",
"cancel": "Cancel",
"delete": "Delete",
"edit": "Edit",
"add": "Add",
"submit": "Submit",
"back": "Back",
"next": "Next",
"confirm": "Confirm"
},
"units": {
"metric": "Metric",
"imperial": "Imperial",
"ml": "ml",
"oz": "oz",
"cm": "cm",
"in": "in",
"kg": "kg",
"lb": "lb"
}
}
```
---
## Phase 3: Custom Hooks
### 3.1 useTranslation Hook
**File**: `hooks/useTranslation.ts` (NEW)
- Re-export from react-i18next with type safety
- Custom hook for easier usage
### 3.2 useLocale Hook
**File**: `hooks/useLocale.ts` (NEW)
- Get current locale
- Change locale
- Get available locales
- Get locale display name
### 3.3 useFormatting Hook
**File**: `hooks/useFormatting.ts` (NEW)
- Format dates based on locale
- Format numbers based on locale
- Format currency based on locale
- Format units based on preference
---
## Phase 4: Measurement Unit Preference
### 4.1 Backend Schema Update
**File**: `src/database/migrations/V0XX_add_measurement_preference.sql` (NEW)
```sql
ALTER TABLE users ADD COLUMN measurement_unit VARCHAR(10) DEFAULT 'metric';
-- Values: 'metric' or 'imperial'
```
### 4.2 Update User Entity
**File**: `src/database/entities/user.entity.ts` (MODIFY)
Add field:
```typescript
@Column({ name: 'measurement_unit', default: 'metric' })
measurementUnit: 'metric' | 'imperial';
```
### 4.3 Update User DTOs
**Files**:
- `src/modules/auth/dto/register.dto.ts` (MODIFY)
- `src/modules/auth/dto/update-profile.dto.ts` (MODIFY)
Add optional `measurementUnit` field.
### 4.4 API Endpoints
**File**: `src/modules/auth/auth.controller.ts` (MODIFY)
- PATCH `/api/v1/auth/profile` - Include measurementUnit in update
---
## Phase 5: Frontend User Preferences
### 5.1 Redux State
**File**: `store/slices/userSlice.ts` (MODIFY)
Add to user state:
```typescript
interface UserState {
// ... existing fields
language: string;
measurementUnit: 'metric' | 'imperial';
}
```
### 5.2 Language Selector Component
**File**: `components/settings/LanguageSelector.tsx` (NEW)
Features:
- Dropdown with 5 language options
- Flag icons for each language
- Updates user preference on change
- Persists to backend
- Updates i18n instance
### 5.3 Measurement Unit Selector Component
**File**: `components/settings/MeasurementUnitSelector.tsx` (NEW)
Features:
- Toggle or dropdown (Metric/Imperial)
- Updates user preference on change
- Persists to backend
- Shows example conversions
---
## Phase 6: Onboarding Flow Integration
### 6.1 Update Onboarding Page
**File**: `app/(auth)/onboarding/page.tsx` (MODIFY)
Add new steps:
1. Language selection (Step 2)
2. Measurement unit selection (Step 3)
### 6.2 Onboarding Language Step Component
**File**: `components/onboarding/LanguageStep.tsx` (NEW)
- Large, visual language selector
- Show language names in native script
- Save to Redux state
- Update i18n immediately
### 6.3 Onboarding Measurement Step Component
**File**: `components/onboarding/MeasurementStep.tsx` (NEW)
- Visual metric/imperial selector
- Show examples (ml vs oz, cm vs in)
- Save to Redux state
### 6.4 Update Onboarding API Call
**File**: `app/(auth)/onboarding/page.tsx` (MODIFY)
Include language and measurementUnit in profile update call.
---
## Phase 7: Settings Page Integration
### 7.1 Update Settings Page
**File**: `app/settings/page.tsx` (MODIFY)
Add new sections:
- **Language & Region** section
- Language selector
- Measurement unit selector
### 7.2 Settings UI Components
**Files**:
- `components/settings/LanguageSettings.tsx` (NEW)
- `components/settings/MeasurementSettings.tsx` (NEW)
---
## Phase 8: Unit Conversion Utilities
### 8.1 Conversion Utility
**File**: `lib/units/conversions.ts` (NEW)
Functions:
- `mlToOz(ml: number): number`
- `ozToMl(oz: number): number`
- `kgToLb(kg: number): number`
- `lbToKg(lb: number): number`
- `cmToIn(cm: number): number`
- `inToCm(in: number): number`
### 8.2 Format Unit Hook
**File**: `hooks/useUnitFormat.ts` (NEW)
- Get user's measurement preference
- Format value with correct unit
- Convert between units
- Display with locale-specific formatting
---
## Phase 9: Apply Localization Throughout App
### 9.1 Update All Pages
Replace hardcoded strings with translation keys:
**Priority Pages**:
1. **Dashboard** (`app/page.tsx`)
- Nav items, headings, button labels
- Activity type labels
- Summary labels
2. **Authentication** (`app/(auth)/`)
- Login, Register, Forgot Password
- Form labels, placeholders, errors
3. **Tracking** (`app/track/`)
- Feeding, Sleep, Diaper pages
- Form labels, unit labels
- Apply unit conversions
4. **Children** (`app/children/page.tsx`)
- Child management labels
- Form fields
5. **Family** (`app/family/page.tsx`)
- Family management labels
6. **AI Assistant** (`app/ai-assistant/page.tsx`)
- Chat interface labels
- Placeholder text
7. **Analytics** (`app/analytics/page.tsx`)
- Chart labels, insights
8. **Settings** (`app/settings/page.tsx`)
- All settings labels
### 9.2 Update Components
Replace hardcoded strings in shared components:
- `components/layouts/AppShell/` (navigation)
- `components/common/` (buttons, dialogs)
- `components/features/` (activity cards, etc.)
---
## Phase 10: Date/Time Localization
### 10.1 Date Formatting Utility
**File**: `lib/i18n/date-formats.ts` (NEW)
Using date-fns with locales:
```typescript
import { format } from 'date-fns';
import { enUS, es, fr, ptBR, zhCN } from 'date-fns/locale';
const locales = { en: enUS, es, fr, pt: ptBR, zh: zhCN };
export function formatDate(date: Date, formatStr: string, locale: string) {
return format(date, formatStr, { locale: locales[locale] });
}
```
### 10.2 Update Date Displays
Apply locale-aware date formatting:
- Activity timestamps
- Child birth dates
- Analytics date ranges
---
## Phase 11: Number Localization
### 11.1 Number Formatting Utility
**File**: `lib/i18n/number-formats.ts` (NEW)
Using Intl.NumberFormat:
```typescript
export function formatNumber(value: number, locale: string) {
return new Intl.NumberFormat(locale).format(value);
}
export function formatDecimal(value: number, locale: string, decimals = 1) {
return new Intl.NumberFormat(locale, {
minimumFractionDigits: decimals,
maximumFractionDigits: decimals,
}).format(value);
}
```
### 11.2 Apply Number Formatting
- Activity amounts (ml/oz)
- Sleep duration (hours)
- Weight/height measurements
---
## Phase 12: Tracking Forms with Unit Preferences
### 12.1 Update Feeding Form
**File**: `app/track/feeding/page.tsx` (MODIFY)
- Show ml or oz input based on preference
- Convert to metric for API storage
- Display in user's preferred unit
### 12.2 Update Child Profile Form
**File**: `app/children/page.tsx` (MODIFY)
- Weight input (kg/lb)
- Height input (cm/in)
- Convert for API storage
### 12.3 Universal Input Component
**File**: `components/forms/UnitInput.tsx` (NEW)
Props:
- `type: 'volume' | 'weight' | 'height'`
- `value: number`
- `onChange: (value: number) => void`
- Auto-convert based on user preference
---
## Phase 13: Translation Files Content
### 13.1 English Translations (Base)
**Estimate**: ~500-800 translation keys across all files
Create complete English translations for:
- All UI strings
- All form labels/placeholders
- All error messages
- All validation messages
### 13.2 Professional Translation
**Recommendation**: Use professional translation service for:
- Spanish (es-ES)
- French (fr-FR)
- Portuguese (pt-BR)
- Simplified Chinese (zh-CN)
**Alternative**: Use AI-assisted translation + native speaker review
---
## Phase 14: Testing
### 14.1 Translation Coverage Test
- Verify all strings are externalized
- No hardcoded English strings remain
- All translation keys exist in all languages
### 14.2 Language Switching Test
- Switch between all 5 languages
- Verify UI updates correctly
- Verify no layout breaks
### 14.3 Unit Conversion Test
- Test all conversions (ml↔oz, kg↔lb, cm↔in)
- Verify correct rounding
- Verify storage in consistent units (metric)
### 14.4 Date/Time Test
- Verify dates display correctly per locale
- Test all date formats (short, long, relative)
### 14.5 RTL Support (Future)
**Note**: Chinese doesn't require RTL, but document for future Arabic support
---
## Phase 15: Documentation
### 15.1 Update Implementation Gaps
**File**: `docs/implementation-gaps.md` (MODIFY)
Mark localization as ✅ COMPLETED
### 15.2 Developer Guide
**File**: `docs/LOCALIZATION_GUIDE.md` (NEW)
Document:
- How to add new translation keys
- How to add new languages
- Translation file structure
- Best practices
### 15.3 Update User Documentation
Document language and measurement preferences in user guide
---
## Implementation Order
### Day 1: Framework & Structure
1. ✅ Install dependencies
2. ✅ Create i18n configuration
3. ✅ Create i18n provider
4. ✅ Create hooks (useTranslation, useLocale, useFormatting)
5. ✅ Set up translation file structure
6. ✅ Create English base translations (common, auth, dashboard)
### Day 2: Preferences & Components
7. ✅ Backend schema update for measurementUnit
8. ✅ Update User entity and DTOs
9. ✅ Create LanguageSelector component
10. ✅ Create MeasurementUnitSelector component
11. ✅ Update onboarding flow
12. ✅ Update settings page
13. ✅ Create unit conversion utilities
### Day 3: Apply Throughout App
14. ✅ Update all pages with translations
15. ✅ Apply unit conversions to tracking forms
16. ✅ Apply date/time localization
17. ✅ Complete all English translations
18. ✅ Test language switching
19. ✅ Test unit conversions
### Post-Implementation (Optional)
20. Professional translation for other 4 languages
21. Native speaker review
22. Documentation updates
---
## Key Files Checklist
### New Files (27 total)
- [ ] `lib/i18n/config.ts`
- [ ] `components/providers/I18nProvider.tsx`
- [ ] `hooks/useLocale.ts`
- [ ] `hooks/useFormatting.ts`
- [ ] `hooks/useUnitFormat.ts`
- [ ] `lib/units/conversions.ts`
- [ ] `lib/i18n/date-formats.ts`
- [ ] `lib/i18n/number-formats.ts`
- [ ] `components/settings/LanguageSelector.tsx`
- [ ] `components/settings/MeasurementUnitSelector.tsx`
- [ ] `components/settings/LanguageSettings.tsx`
- [ ] `components/settings/MeasurementSettings.tsx`
- [ ] `components/onboarding/LanguageStep.tsx`
- [ ] `components/onboarding/MeasurementStep.tsx`
- [ ] `components/forms/UnitInput.tsx`
- [ ] `locales/en/*.json` (11 files)
- [ ] `locales/es/*.json` (11 files - future)
- [ ] `locales/fr/*.json` (11 files - future)
- [ ] `locales/pt/*.json` (11 files - future)
- [ ] `locales/zh/*.json` (11 files - future)
- [ ] `src/database/migrations/V0XX_add_measurement_preference.sql`
- [ ] `docs/LOCALIZATION_GUIDE.md`
### Modified Files (15 total)
- [ ] `package.json`
- [ ] `app/layout.tsx`
- [ ] `store/slices/userSlice.ts`
- [ ] `src/database/entities/user.entity.ts`
- [ ] `src/modules/auth/dto/register.dto.ts`
- [ ] `src/modules/auth/dto/update-profile.dto.ts`
- [ ] `app/(auth)/onboarding/page.tsx`
- [ ] `app/settings/page.tsx`
- [ ] `app/page.tsx` (dashboard)
- [ ] `app/track/feeding/page.tsx`
- [ ] `app/track/sleep/page.tsx`
- [ ] `app/track/diaper/page.tsx`
- [ ] `app/children/page.tsx`
- [ ] `app/family/page.tsx`
- [ ] `docs/implementation-gaps.md`
---
## Success Criteria
### ✅ Functionality
- [ ] All 5 languages selectable and functional
- [ ] Language preference persists across sessions
- [ ] Measurement unit preference persists across sessions
- [ ] All UI strings externalized (no hardcoded English)
- [ ] Unit conversions work correctly (ml↔oz, kg↔lb, cm↔in)
- [ ] Dates display correctly per locale
- [ ] Numbers format correctly per locale
### ✅ User Experience
- [ ] Language can be selected in onboarding
- [ ] Language can be changed in settings
- [ ] Measurement unit can be selected in onboarding
- [ ] Measurement unit can be changed in settings
- [ ] UI updates immediately when language changes
- [ ] No layout breaks when changing languages
- [ ] Form inputs show correct units based on preference
### ✅ Technical
- [ ] All translation keys defined
- [ ] No missing translation warnings
- [ ] Type-safe translation usage (TypeScript)
- [ ] Backend stores preferences correctly
- [ ] Redux state syncs with backend
---
## Notes
### Translation Best Practices
1. Use namespaces to organize translations
2. Use interpolation for dynamic values: `t('welcome', { name })`
3. Use pluralization: `t('items', { count })`
4. Keep keys descriptive: `auth.login.emailLabel` not `auth.e1`
5. Avoid concatenation, use complete sentences
### Unit Conversion Strategy
- **Storage**: Always store in metric (ml, kg, cm) in database
- **Display**: Convert to user's preferred unit for display
- **Input**: Accept user's preferred unit, convert to metric before API call
- **Consistency**: Ensure all measurements use the same preference
### Performance Considerations
- Lazy load translation files per namespace
- Cache translations in browser
- Preload critical translations (common, errors)
### Future Enhancements
- Add more languages (Arabic, German, Hindi, etc.)
- Add more units (temperature: °C/°F)
- Add regional date formats (MM/DD vs DD/MM)
- Add time format preferences (12h vs 24h)
---
**Total Estimated Effort**: 2-3 days
**Complexity**: Medium
**Priority**: HIGH (Pre-Launch)
**Dependencies**: None (can start immediately)

View File

@@ -1,784 +0,0 @@
# Localization Implementation Plan
**Created**: October 3, 2025
**Priority**: HIGH (Pre-Launch)
**Estimated Duration**: 2-3 days
## Overview
Implement comprehensive internationalization (i18n) support for the Maternal App with 5 languages and measurement unit preferences.
## Supported Languages
1. **English (en-US)** - Primary/Default
2. **Spanish (es-ES)**
3. **French (fr-FR)**
4. **Portuguese (pt-BR)**
5. **Simplified Chinese (zh-CN)**
## Current Status - Updated October 3, 2025
### ✅ Already Completed (Backend)
- Backend multilanguage support for AI responses
- AI safety responses in 5 languages
- MultiLanguageService with language detection
### ✅ Completed (Frontend - Phases 1-9)
-**Phase 1**: i18next framework installed and configured
-**Phase 2**: Translation files structure created (40 files: 5 languages × 8 namespaces)
-**Phase 3**: Custom hooks created (useTranslation, useLocale, useFormatting)
-**Phase 4**: Backend user schema updated with measurementUnit in preferences JSONB
-**Phase 5**: Language & measurement selectors in Settings page
-**Phase 7**: Settings page fully localized with preferences
-**Phase 8**: Measurement unit conversion utilities implemented
-**Phase 9**: Applied localization to core pages:
- Login & authentication pages
- Dashboard with welcome message, quick actions, summary
- Navigation (AppShell, MobileNav, TabBar)
- Track main page (activity selection)
- Children page (with age formatting & pluralization)
- All connection status indicators
### ✅ Translation Files Created (40 files)
- `common.json` - UI strings, navigation, connection (all 5 languages)
- `auth.json` - Authentication pages (all 5 languages)
- `dashboard.json` - Dashboard/home page (all 5 languages)
- `tracking.json` - Activity tracking (all 5 languages)
- `children.json` - Child management (all 5 languages)
- `settings.json` - Settings page (all 5 languages)
- `ai.json` - AI assistant (all 5 languages)
- `errors.json` - Error messages (all 5 languages)
### ⏳ Remaining To Be Implemented
- Language selector in onboarding flow (Phase 6)
- Individual tracking pages (feeding, sleep, diaper, medicine) with unit conversions (Phase 12)
- Family management page localization
- Analytics/insights page localization
- Date/time localization throughout app (Phase 10)
- Number formatting per locale (Phase 11)
- Professional translation review (Phase 13.2)
- Comprehensive testing (Phase 14)
---
## Phase 1: Framework Setup ✅ COMPLETED
### 1.1 Install Dependencies - latest versions only! ✅
**Files**: `package.json`
```bash
npm install i18next react-i18next i18next-browser-languagedetector
npm install date-fns # Already installed, confirm locales
```
**Packages**:
- `i18next` - Core i18n framework
- `react-i18next` - React bindings
- `i18next-browser-languagedetector` - Auto-detect user language
### 1.2 Create i18n Configuration ✅
**File**: `lib/i18n/config.ts` (CREATED)
- ✅ Initialize i18next
- ✅ Configure language detector
- ✅ Set up fallback language (en-US)
- ✅ Configure interpolation
- ✅ Load translation resources
### 1.3 Create i18n Provider ✅
**File**: `components/providers/I18nProvider.tsx` (CREATED)
- ✅ Wrap app with I18nextProvider
- ✅ Initialize i18n on mount
- ✅ Handle language loading states
### 1.4 Update Root Layout ✅
**File**: `app/layout.tsx` (MODIFIED)
- ✅ Add I18nProvider to provider stack
- ⏳ Set html lang attribute dynamically (TODO)
---
## Phase 2: Translation Files Structure ✅ COMPLETED
### 2.1 Directory Structure
```
locales/
├── en/
│ ├── common.json # Common UI strings (buttons, labels, etc.)
│ ├── auth.json # Authentication pages
│ ├── dashboard.json # Dashboard/home page
│ ├── tracking.json # Activity tracking
│ ├── children.json # Child management
│ ├── family.json # Family management
│ ├── ai.json # AI assistant
│ ├── analytics.json # Analytics/insights
│ ├── settings.json # Settings page
│ ├── onboarding.json # Onboarding flow
│ ├── errors.json # Error messages
│ └── validation.json # Form validation messages
├── es/
│ └── [same structure]
├── fr/
│ └── [same structure]
├── pt/
│ └── [same structure]
└── zh/
└── [same structure]
```
### 2.2 Translation Keys Structure
**Example - common.json**:
```json
{
"nav": {
"dashboard": "Dashboard",
"track": "Track",
"children": "Children",
"family": "Family",
"ai": "AI Assistant",
"analytics": "Analytics",
"settings": "Settings"
},
"buttons": {
"save": "Save",
"cancel": "Cancel",
"delete": "Delete",
"edit": "Edit",
"add": "Add",
"submit": "Submit",
"back": "Back",
"next": "Next",
"confirm": "Confirm"
},
"units": {
"metric": "Metric",
"imperial": "Imperial",
"ml": "ml",
"oz": "oz",
"cm": "cm",
"in": "in",
"kg": "kg",
"lb": "lb"
}
}
```
---
## Phase 3: Custom Hooks ✅ COMPLETED
### 3.1 useTranslation Hook ✅
**File**: `hooks/useTranslation.ts` (CREATED)
- ✅ Re-export from react-i18next with type safety
- ✅ Custom hook for easier usage
### 3.2 useLocale Hook ✅
**File**: `hooks/useLocale.ts` (CREATED)
- ✅ Get current locale
- ✅ Change locale
- ✅ Get available locales
- ✅ Get locale display name
- ✅ Measurement system management
### 3.3 useFormatting Hook ✅
**File**: `hooks/useFormatting.ts` (CREATED)
- ✅ Format dates based on locale
- ✅ Format numbers based on locale
- ✅ Format currency based on locale
- ✅ Format units based on preference
---
## Phase 4: Measurement Unit Preference ✅ COMPLETED
### 4.1 Backend Schema Update ✅
**Implementation**: Used existing `preferences` JSONB column from V005_add_user_preferences.sql
- No new migration needed - reused existing preferences column
- Added `measurementUnit` as optional field in preferences object
### 4.2 Update User Entity ✅
**File**: `src/database/entities/user.entity.ts` (MODIFIED)
Added to preferences type:
```typescript
@Column({ type: 'jsonb', nullable: true })
preferences?: {
notifications?: boolean;
emailUpdates?: boolean;
darkMode?: boolean;
measurementUnit?: 'metric' | 'imperial';
};
```
### 4.3 Update User DTOs ✅
**File**: `src/modules/auth/dto/update-profile.dto.ts` (CREATED)
Created with validation:
```typescript
export class UserPreferencesDto {
@IsOptional()
@IsIn(['metric', 'imperial'])
measurementUnit?: 'metric' | 'imperial';
}
```
### 4.4 API Endpoints ✅
**File**: `src/modules/auth/auth.controller.ts` (MODIFIED)
- PATCH `/api/v1/auth/profile` - Updated to use UpdateProfileDto with measurementUnit support
- Properly typed and validated
---
## Phase 5: Frontend User Preferences ✅ PARTIALLY COMPLETED
### 5.1 Redux State ⏳
**File**: `store/slices/userSlice.ts` (TODO)
Add to user state:
```typescript
interface UserState {
// ... existing fields
language: string;
measurementUnit: 'metric' | 'imperial';
}
```
### 5.2 Language Selector Component ✅
**File**: `components/settings/LanguageSelector.tsx` (CREATED)
Features:
- ✅ Dropdown with 5 language options
- ✅ Shows language names in native script
- ✅ Updates user preference on change
- ⏳ Persists to backend (pending backend schema)
- ✅ Updates i18n instance
### 5.3 Measurement Unit Selector Component ✅
**File**: `components/settings/MeasurementUnitSelector.tsx` (CREATED)
Features:
- ✅ Dropdown (Metric/Imperial)
- ✅ Updates user preference on change
- ⏳ Persists to backend (pending backend schema)
- ✅ Shows unit examples
---
## Phase 6: Onboarding Flow Integration ❌ TODO
### 6.1 Update Onboarding Page
**File**: `app/(auth)/onboarding/page.tsx` (MODIFY)
Add new steps:
1. Language selection (Step 2)
2. Measurement unit selection (Step 3)
### 6.2 Onboarding Language Step Component
**File**: `components/onboarding/LanguageStep.tsx` (NEW)
- Large, visual language selector
- Show language names in native script
- Save to Redux state
- Update i18n immediately
### 6.3 Onboarding Measurement Step Component
**File**: `components/onboarding/MeasurementStep.tsx` (NEW)
- Visual metric/imperial selector
- Show examples (ml vs oz, cm vs in)
- Save to Redux state
### 6.4 Update Onboarding API Call
**File**: `app/(auth)/onboarding/page.tsx` (MODIFY)
Include language and measurementUnit in profile update call.
---
## Phase 7: Settings Page Integration ✅ COMPLETED
### 7.1 Update Settings Page ✅
**File**: `app/settings/page.tsx` (MODIFIED)
Add new sections:
-**Preferences** section
- ✅ Language selector
- ✅ Measurement unit selector
### 7.2 Settings UI Components ✅
**Files**:
-`components/settings/LanguageSelector.tsx` (CREATED)
-`components/settings/MeasurementUnitSelector.tsx` (CREATED)
---
## Phase 8: Unit Conversion Utilities ✅ COMPLETED
### 8.1 Conversion Utility ✅
**File**: `lib/utils/unitConversion.ts` (CREATED)
Functions:
-`convertWeight` / `convertWeightToKg`
-`convertHeight` / `convertHeightToCm`
-`convertTemperature` / `convertTemperatureToCelsius`
-`convertVolume` / `convertVolumeToMl`
-`getUnitSymbol`
-`getConversionFactor`
### 8.2 Format Unit Hook ✅
**File**: `hooks/useFormatting.ts` (CREATED)
- ✅ Get user's measurement preference
- ✅ Format value with correct unit
- ✅ Convert between units
- ✅ Display with locale-specific formatting
---
## Phase 9: Apply Localization Throughout App ✅ PARTIALLY COMPLETED
### 9.1 Update All Pages - Status
**✅ Completed Priority Pages**:
1.**Dashboard** (`app/page.tsx`)
- Welcome message with user name interpolation
- Quick actions (all 6 activity cards)
- Today's summary with child name interpolation
- Next predicted activity with variable interpolation
- All UI labels translated in 5 languages
2.**Authentication** (`app/(auth)/login/page.tsx`)
- Login form labels (email, password)
- Submit button, forgot password link
- Social login buttons (Google, Apple)
- Biometric authentication (Face ID/Touch ID)
- Sign up link and all helper text
3.**Track Main Page** (`app/track/page.tsx`)
- Track Activity title and subtitle
- All 5 activity type labels (Feeding, Sleep, Diaper, Medicine, Activity)
- Translated in all 5 languages
4.**Children** (`app/children/page.tsx`)
- Page title and subtitle
- Add/Edit child buttons
- Empty state messages
- Age calculation with proper pluralization (year/years, month/months)
- All error messages
- Gender labels
**❌ Remaining Pages**:
5.**Individual Tracking Pages** (`app/track/feeding/`, etc.)
- Feeding, Sleep, Diaper, Medicine detail pages
- Form labels, unit labels
- Apply unit conversions (Phase 12)
6.**Family** (`app/family/page.tsx`)
- Family management labels
7.**AI Assistant** (`app/ai-assistant/page.tsx`)
- Chat interface already uses AI translations from backend
- Frontend labels may need localization
8.**Analytics** (`app/analytics/page.tsx`)
- Chart labels, insights
9.**Settings** (`app/settings/page.tsx`)
- Already completed in Phase 7
### 9.2 Update Components - Status
**✅ Completed Components**:
-`components/layouts/AppShell/AppShell.tsx` - Connection status, presence indicators
-`components/layouts/MobileNav/MobileNav.tsx` - Navigation menu items, logout
-`components/layouts/TabBar/TabBar.tsx` - Bottom navigation tabs
-`components/settings/LanguageSelector.tsx` - Language preference UI
-`components/settings/MeasurementUnitSelector.tsx` - Measurement preference UI
**❌ Remaining Components**:
-`components/common/` - Common dialogs, buttons (may need review)
-`components/features/` - Activity cards, forms (need review)
-`components/children/` - Child dialogs (ChildDialog, DeleteConfirmDialog)
-`components/family/` - Family components
---
## Phase 10: Date/Time Localization
### 10.1 Date Formatting Utility
**File**: `lib/i18n/date-formats.ts` (NEW)
Using date-fns with locales:
```typescript
import { format } from 'date-fns';
import { enUS, es, fr, ptBR, zhCN } from 'date-fns/locale';
const locales = { en: enUS, es, fr, pt: ptBR, zh: zhCN };
export function formatDate(date: Date, formatStr: string, locale: string) {
return format(date, formatStr, { locale: locales[locale] });
}
```
### 10.2 Update Date Displays
Apply locale-aware date formatting:
- Activity timestamps
- Child birth dates
- Analytics date ranges
---
## Phase 11: Number Localization
### 11.1 Number Formatting Utility
**File**: `lib/i18n/number-formats.ts` (NEW)
Using Intl.NumberFormat:
```typescript
export function formatNumber(value: number, locale: string) {
return new Intl.NumberFormat(locale).format(value);
}
export function formatDecimal(value: number, locale: string, decimals = 1) {
return new Intl.NumberFormat(locale, {
minimumFractionDigits: decimals,
maximumFractionDigits: decimals,
}).format(value);
}
```
### 11.2 Apply Number Formatting
- Activity amounts (ml/oz)
- Sleep duration (hours)
- Weight/height measurements
---
## Phase 12: Tracking Forms with Unit Preferences
### 12.1 Update Feeding Form
**File**: `app/track/feeding/page.tsx` (MODIFY)
- Show ml or oz input based on preference
- Convert to metric for API storage
- Display in user's preferred unit
### 12.2 Update Child Profile Form
**File**: `app/children/page.tsx` (MODIFY)
- Weight input (kg/lb)
- Height input (cm/in)
- Convert for API storage
### 12.3 Universal Input Component
**File**: `components/forms/UnitInput.tsx` (NEW)
Props:
- `type: 'volume' | 'weight' | 'height'`
- `value: number`
- `onChange: (value: number) => void`
- Auto-convert based on user preference
---
## Phase 13: Translation Files Content
### 13.1 English Translations (Base)
**Estimate**: ~500-800 translation keys across all files
Create complete English translations for:
- All UI strings
- All form labels/placeholders
- All error messages
- All validation messages
### 13.2 Professional Translation
**Recommendation**: Use professional translation service for:
- Spanish (es-ES)
- French (fr-FR)
- Portuguese (pt-BR)
- Simplified Chinese (zh-CN)
**Alternative**: Use AI-assisted translation + native speaker review
---
## Phase 14: Testing
### 14.1 Translation Coverage Test
- Verify all strings are externalized
- No hardcoded English strings remain
- All translation keys exist in all languages
### 14.2 Language Switching Test
- Switch between all 5 languages
- Verify UI updates correctly
- Verify no layout breaks
### 14.3 Unit Conversion Test
- Test all conversions (ml↔oz, kg↔lb, cm↔in)
- Verify correct rounding
- Verify storage in consistent units (metric)
### 14.4 Date/Time Test
- Verify dates display correctly per locale
- Test all date formats (short, long, relative)
### 14.5 RTL Support (Future)
**Note**: Chinese doesn't require RTL, but document for future Arabic support
---
## Phase 15: Documentation
### 15.1 Update Implementation Gaps
**File**: `docs/implementation-gaps.md` (MODIFY)
Mark localization as ✅ COMPLETED
### 15.2 Developer Guide
**File**: `docs/LOCALIZATION_GUIDE.md` (NEW)
Document:
- How to add new translation keys
- How to add new languages
- Translation file structure
- Best practices
### 15.3 Update User Documentation
Document language and measurement preferences in user guide
---
## Implementation Order
### Day 1: Framework & Structure
1. ✅ Install dependencies
2. ✅ Create i18n configuration
3. ✅ Create i18n provider
4. ✅ Create hooks (useTranslation, useLocale, useFormatting)
5. ✅ Set up translation file structure
6. ✅ Create English base translations (common, auth, dashboard)
### Day 2: Preferences & Components
7. ✅ Backend schema update for measurementUnit
8. ✅ Update User entity and DTOs
9. ✅ Create LanguageSelector component
10. ✅ Create MeasurementUnitSelector component
11. ✅ Update onboarding flow
12. ✅ Update settings page
13. ✅ Create unit conversion utilities
### Day 3: Apply Throughout App
14. ✅ Update all pages with translations
15. ✅ Apply unit conversions to tracking forms
16. ✅ Apply date/time localization
17. ✅ Complete all English translations
18. ✅ Test language switching
19. ✅ Test unit conversions
### Post-Implementation (Optional)
20. Professional translation for other 4 languages
21. Native speaker review
22. Documentation updates
---
## Key Files Checklist
### New Files (27 total)
- [ ] `lib/i18n/config.ts`
- [ ] `components/providers/I18nProvider.tsx`
- [ ] `hooks/useLocale.ts`
- [ ] `hooks/useFormatting.ts`
- [ ] `hooks/useUnitFormat.ts`
- [ ] `lib/units/conversions.ts`
- [ ] `lib/i18n/date-formats.ts`
- [ ] `lib/i18n/number-formats.ts`
- [ ] `components/settings/LanguageSelector.tsx`
- [ ] `components/settings/MeasurementUnitSelector.tsx`
- [ ] `components/settings/LanguageSettings.tsx`
- [ ] `components/settings/MeasurementSettings.tsx`
- [ ] `components/onboarding/LanguageStep.tsx`
- [ ] `components/onboarding/MeasurementStep.tsx`
- [ ] `components/forms/UnitInput.tsx`
- [ ] `locales/en/*.json` (11 files)
- [ ] `locales/es/*.json` (11 files - future)
- [ ] `locales/fr/*.json` (11 files - future)
- [ ] `locales/pt/*.json` (11 files - future)
- [ ] `locales/zh/*.json` (11 files - future)
- [ ] `src/database/migrations/V0XX_add_measurement_preference.sql`
- [ ] `docs/LOCALIZATION_GUIDE.md`
### Modified Files (15 total)
- [ ] `package.json`
- [ ] `app/layout.tsx`
- [ ] `store/slices/userSlice.ts`
- [ ] `src/database/entities/user.entity.ts`
- [ ] `src/modules/auth/dto/register.dto.ts`
- [ ] `src/modules/auth/dto/update-profile.dto.ts`
- [ ] `app/(auth)/onboarding/page.tsx`
- [ ] `app/settings/page.tsx`
- [ ] `app/page.tsx` (dashboard)
- [ ] `app/track/feeding/page.tsx`
- [ ] `app/track/sleep/page.tsx`
- [ ] `app/track/diaper/page.tsx`
- [ ] `app/children/page.tsx`
- [ ] `app/family/page.tsx`
- [ ] `docs/implementation-gaps.md`
---
## Success Criteria
### ✅ Functionality
- [ ] All 5 languages selectable and functional
- [ ] Language preference persists across sessions
- [ ] Measurement unit preference persists across sessions
- [ ] All UI strings externalized (no hardcoded English)
- [ ] Unit conversions work correctly (ml↔oz, kg↔lb, cm↔in)
- [ ] Dates display correctly per locale
- [ ] Numbers format correctly per locale
### ✅ User Experience
- [ ] Language can be selected in onboarding
- [ ] Language can be changed in settings
- [ ] Measurement unit can be selected in onboarding
- [ ] Measurement unit can be changed in settings
- [ ] UI updates immediately when language changes
- [ ] No layout breaks when changing languages
- [ ] Form inputs show correct units based on preference
### ✅ Technical
- [ ] All translation keys defined
- [ ] No missing translation warnings
- [ ] Type-safe translation usage (TypeScript)
- [ ] Backend stores preferences correctly
- [ ] Redux state syncs with backend
---
## Notes
### Translation Best Practices
1. Use namespaces to organize translations
2. Use interpolation for dynamic values: `t('welcome', { name })`
3. Use pluralization: `t('items', { count })`
4. Keep keys descriptive: `auth.login.emailLabel` not `auth.e1`
5. Avoid concatenation, use complete sentences
### Unit Conversion Strategy
- **Storage**: Always store in metric (ml, kg, cm) in database
- **Display**: Convert to user's preferred unit for display
- **Input**: Accept user's preferred unit, convert to metric before API call
- **Consistency**: Ensure all measurements use the same preference
### Performance Considerations
- Lazy load translation files per namespace
- Cache translations in browser
- Preload critical translations (common, errors)
### Future Enhancements
- Add more languages (Arabic, German, Hindi, etc.)
- Add more units (temperature: °C/°F)
- Add regional date formats (MM/DD vs DD/MM)
- Add time format preferences (12h vs 24h)
---
## Remaining Tasks Summary
### 🔴 High Priority (Core Functionality)
1. **Individual Tracking Pages with Unit Conversions** (Phase 12)
- `/app/track/feeding/page.tsx` - Volume conversion (ml ↔ oz)
- `/app/track/sleep/page.tsx` - Duration formatting
- `/app/track/diaper/page.tsx` - Type labels
- `/app/track/medicine/page.tsx` - Dosage with units
- Implement UnitInput component for automatic conversion
- **Estimated Effort**: 4-6 hours
2. **Child Dialog Components Localization**
- `components/children/ChildDialog.tsx` - Form labels
- `components/children/DeleteConfirmDialog.tsx` - Confirmation text
- **Estimated Effort**: 1 hour
3. **Date/Time Localization** (Phase 10)
- Apply date-fns with locale to all date displays
- Activity timestamps
- Child birth dates
- Analytics date ranges
- **Estimated Effort**: 2-3 hours
### 🟡 Medium Priority (Nice to Have)
4. **Onboarding Flow** (Phase 6)
- Add language selection step
- Add measurement unit selection step
- Save preferences during onboarding
- **Estimated Effort**: 2-3 hours
5. **Family Management Page**
- `app/family/page.tsx` localization
- Family member labels, invitation flow
- **Estimated Effort**: 1-2 hours
6. **Number Formatting** (Phase 11)
- Apply Intl.NumberFormat throughout
- Weight/height values
- Activity counts
- **Estimated Effort**: 1-2 hours
### 🟢 Low Priority (Future Enhancements)
7. **Analytics/Insights Page**
- Chart labels
- Insight descriptions
- **Estimated Effort**: 2-3 hours
8. **Professional Translation Review** (Phase 13.2)
- Review all 4 non-English languages
- Native speaker validation
- Cultural appropriateness check
- **Estimated Effort**: External service, 1-2 weeks
9. **Comprehensive Testing** (Phase 14)
- Translation coverage test
- Language switching test
- Unit conversion test
- Date/time formatting test
- **Estimated Effort**: 2-4 hours
10. **Documentation** (Phase 15)
- Create LOCALIZATION_GUIDE.md
- Update implementation-gaps.md
- Developer best practices
- **Estimated Effort**: 1-2 hours
### 📊 Progress Tracking
**Completed**: 9 phases (1-5, 7-9)
**In Progress**: 0 phases
**Remaining**: 6 major phases (6, 10-15)
**Overall Completion**: ~65% (core functionality)
**Estimated Time to Full Completion**:
- High Priority: 8-11 hours
- Medium Priority: 4-7 hours
- Low Priority: 5-9 hours
- **Total Remaining**: 17-27 hours (2-3.5 days)
---
**Total Project Effort**: 2-3 days (completed) + 2-3.5 days (remaining) = 4-6.5 days
**Complexity**: Medium
**Priority**: HIGH (Pre-Launch)
**Current Status**: Core functionality 65% complete, production-ready for MVP

File diff suppressed because it is too large Load Diff

View File

@@ -1,943 +0,0 @@
# API Gateway Architecture & Security Implementation Plan
**Created**: October 3, 2025
**Status**: Planning Phase
**Priority**: High - Security & Scalability
---
## 📋 Executive Summary
### Current State
- **Backend API**: Directly exposed to internet at `https://maternal-api.noru1.ro`
- **Frontend**: Next.js web app making direct API calls from browser
- **Security Risk**: All API endpoints publicly accessible
- **Architecture**: Monolithic - single NestJS backend serving REST, GraphQL, and WebSocket
### Problem Statement
With the current architecture:
1. Backend API is fully exposed to the internet (security risk)
2. No rate limiting at infrastructure level
3. Direct API access bypasses Next.js middleware/auth checks
4. Future mobile apps will need direct API access
5. WebSocket connections need persistent connection handling
6. GraphQL endpoint requires different security model than REST
### Proposed Solution
Implement an **API Gateway pattern** with:
- Next.js API routes as BFF (Backend-for-Frontend) for web app
- Direct backend access for mobile apps (with API key + JWT)
- Nginx/Kong as reverse proxy for rate limiting and SSL termination
- WebSocket gateway for real-time features
- Separate security policies for REST vs GraphQL
---
## 🏗️ Architecture Overview
### Option 1: Next.js API Routes as BFF (Recommended for MVP)
```
┌─────────────────────────────────────────────────────────────┐
│ Internet (HTTPS) │
└─────────────────────────────────────────────────────────────┘
┌─────────────────┐
│ Nginx/Cloudflare│
│ (SSL, WAF, DDoS) │
└─────────────────┘
┌─────────────┴─────────────┐
│ │
▼ ▼
┌───────────────────────┐ ┌─────────────────────┐
│ Next.js Frontend │ │ Mobile Apps │
│ (Port 3030) │ │ (iOS/Android) │
│ │ │ │
│ ┌─────────────────┐ │ └─────────────────────┘
│ │ /api/* Routes │ │ │
│ │ (BFF Layer) │ │ │
│ └─────────────────┘ │ │
└───────────────────────┘ │
│ │
│ (Internal Network) │ (Public API)
│ localhost:3020 │ api.maternal.com
│ │
└──────────┬───────────────┘
┌─────────────────────────┐
│ NestJS Backend │
│ (Port 3020) │
│ │
│ ┌───────────────────┐ │
│ │ REST API │ │
│ │ /api/v1/* │ │
│ └───────────────────┘ │
│ │
│ ┌───────────────────┐ │
│ │ GraphQL │ │
│ │ /graphql │ │
│ └───────────────────┘ │
│ │
│ ┌───────────────────┐ │
│ │ WebSocket │ │
│ │ /ws │ │
│ └───────────────────┘ │
└─────────────────────────┘
┌──────────────────┐
│ PostgreSQL │
│ Redis │
│ MongoDB │
└──────────────────┘
```
### Option 2: Kong API Gateway (Production-Ready)
```
┌─────────────────────────────────────────────────────────────┐
│ Internet (HTTPS) │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────┐
│ Kong API Gateway │
│ (Port 443/8000) │
│ │
│ Plugins: │
│ - Rate Limiting │
│ - JWT Auth │
│ - CORS │
│ - Request Transform │
│ - Response Cache │
└─────────────────────┘
┌─────────────┴─────────────┐
│ │
▼ ▼
┌───────────────────────┐ ┌─────────────────────┐
│ Next.js Frontend │ │ Mobile Apps │
│ (Internal) │ │ (External) │
└───────────────────────┘ └─────────────────────┘
│ │
└──────────┬───────────────┘
┌─────────────────────────┐
│ NestJS Backend │
│ (Internal Network) │
│ Not exposed to web │
└─────────────────────────┘
```
---
## 🎯 Recommended Architecture: Hybrid Approach
### Phase 1: MVP (Current State + BFF)
1. **Web App**: Next.js API routes as BFF (proxy to backend)
2. **Mobile Apps**: Direct backend access with API keys
3. **Backend**: Exposed only to mobile, hidden from web
4. **Timeline**: 1-2 weeks
### Phase 2: Production (Kong Gateway)
1. **All Clients**: Route through Kong API Gateway
2. **Backend**: Completely internal, not exposed
3. **Security**: Centralized auth, rate limiting, logging
4. **Timeline**: 4-6 weeks (post-MVP)
---
## 📝 Implementation Plan: Phase 1 (BFF Pattern)
### Step 1: Create Next.js API Routes as BFF
**Goal**: Proxy all backend requests through Next.js to hide backend URL
**Files to Create**:
```
maternal-web/
├── app/api/
│ ├── proxy/
│ │ ├── route.ts # Generic proxy handler
│ │ └── [...path]/route.ts # Catch-all proxy
│ ├── graphql/
│ │ └── route.ts # GraphQL proxy
│ └── ws/
│ └── route.ts # WebSocket upgrade handler
```
**Implementation**:
#### 1.1 Generic REST API Proxy
**File**: `maternal-web/app/api/proxy/[...path]/route.ts`
```typescript
import { NextRequest, NextResponse } from 'next/server';
const BACKEND_URL = process.env.BACKEND_API_URL || 'http://localhost:3020';
export async function GET(
request: NextRequest,
{ params }: { params: { path: string[] } }
) {
return proxyRequest(request, params.path, 'GET');
}
export async function POST(
request: NextRequest,
{ params }: { params: { path: string[] } }
) {
return proxyRequest(request, params.path, 'POST');
}
export async function PATCH(
request: NextRequest,
{ params }: { params: { path: string[] } }
) {
return proxyRequest(request, params.path, 'PATCH');
}
export async function DELETE(
request: NextRequest,
{ params }: { params: { path: string[] } }
) {
return proxyRequest(request, params.path, 'DELETE');
}
async function proxyRequest(
request: NextRequest,
pathSegments: string[],
method: string
) {
const path = pathSegments.join('/');
const url = new URL(request.url);
const backendUrl = `${BACKEND_URL}/api/v1/${path}${url.search}`;
// Forward headers (excluding host)
const headers = new Headers();
request.headers.forEach((value, key) => {
if (key.toLowerCase() !== 'host' && key.toLowerCase() !== 'connection') {
headers.set(key, value);
}
});
// Add internal API key for backend authentication
headers.set('X-Internal-API-Key', process.env.INTERNAL_API_KEY || '');
try {
const body = method !== 'GET' ? await request.text() : undefined;
const response = await fetch(backendUrl, {
method,
headers,
body,
});
// Forward response headers
const responseHeaders = new Headers();
response.headers.forEach((value, key) => {
responseHeaders.set(key, value);
});
const responseBody = await response.text();
return new NextResponse(responseBody, {
status: response.status,
statusText: response.statusText,
headers: responseHeaders,
});
} catch (error) {
console.error('Proxy error:', error);
return NextResponse.json(
{ error: 'Internal proxy error' },
{ status: 502 }
);
}
}
```
#### 1.2 GraphQL Proxy
**File**: `maternal-web/app/api/graphql/route.ts`
```typescript
import { NextRequest, NextResponse } from 'next/server';
const BACKEND_URL = process.env.BACKEND_API_URL || 'http://localhost:3020';
export async function POST(request: NextRequest) {
const backendUrl = `${BACKEND_URL}/graphql`;
const headers = new Headers();
headers.set('Content-Type', 'application/json');
headers.set('Authorization', request.headers.get('Authorization') || '');
headers.set('X-Internal-API-Key', process.env.INTERNAL_API_KEY || '');
try {
const body = await request.text();
const response = await fetch(backendUrl, {
method: 'POST',
headers,
body,
});
const responseBody = await response.text();
return new NextResponse(responseBody, {
status: response.status,
headers: {
'Content-Type': 'application/json',
},
});
} catch (error) {
console.error('GraphQL proxy error:', error);
return NextResponse.json(
{ errors: [{ message: 'GraphQL proxy error' }] },
{ status: 502 }
);
}
}
// Support GraphQL Playground in development
export async function GET(request: NextRequest) {
if (process.env.NODE_ENV !== 'production') {
const backendUrl = `${BACKEND_URL}/graphql`;
const response = await fetch(backendUrl);
const html = await response.text();
return new NextResponse(html, {
headers: { 'Content-Type': 'text/html' },
});
}
return NextResponse.json(
{ error: 'GraphQL Playground disabled in production' },
{ status: 403 }
);
}
```
#### 1.3 WebSocket Proxy (Next.js Limitation Workaround)
**Note**: Next.js API routes don't support WebSocket upgrades directly. We need to use a custom server or keep WebSocket on backend.
**Option A**: Keep WebSocket endpoint on backend (simpler)
**Option B**: Use Next.js custom server with `ws` library (complex)
**Recommended**: Keep WebSocket on backend, add authentication layer
**File**: `maternal-app-backend/src/families/families.gateway.ts` (modify)
```typescript
import { WebSocketGateway, WebSocketServer, OnGatewayConnection } from '@nestjs/websockets';
import { Server, Socket } from 'socket.io';
@WebSocketGateway({
cors: {
origin: [
'http://localhost:3030',
'https://maternal.noru1.ro',
'https://maternal-web.noru1.ro',
],
credentials: true,
},
})
export class FamiliesGateway implements OnGatewayConnection {
@WebSocketServer()
server: Server;
async handleConnection(client: Socket) {
// Verify internal API key or JWT token
const apiKey = client.handshake.headers['x-internal-api-key'];
const token = client.handshake.auth.token;
if (!apiKey && !token) {
client.disconnect();
return;
}
// Authenticate based on mobile (token) or web (API key)
const isValid = await this.validateConnection(apiKey, token);
if (!isValid) {
client.disconnect();
}
}
}
```
---
### Step 2: Update Frontend to Use BFF
**Files to Modify**:
- `lib/api/client.ts`
- `lib/apollo-client.ts`
- All API utility files
**Changes**:
```typescript
// lib/api/client.ts (before)
const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3020';
// lib/api/client.ts (after)
const API_BASE_URL = '/api/proxy'; // Use Next.js BFF
// lib/apollo-client.ts (before)
uri: process.env.NEXT_PUBLIC_GRAPHQL_URL || 'http://localhost:3020/graphql',
// lib/apollo-client.ts (after)
uri: '/api/graphql', // Use Next.js GraphQL proxy
```
**Environment Variables**:
```bash
# maternal-web/.env.local
# Remove NEXT_PUBLIC_API_URL (security - don't expose backend URL to browser)
# NEXT_PUBLIC_API_URL=https://maternal-api.noru1.ro # DELETE THIS
# Add backend URL for server-side only
BACKEND_API_URL=http://localhost:3020
INTERNAL_API_KEY=your-secret-internal-key-12345
# For WebSocket, keep exposed for now (will secure later)
NEXT_PUBLIC_WS_URL=https://maternal-api.noru1.ro
```
---
### Step 3: Add Internal API Key Authentication to Backend
**Goal**: Backend validates requests from Next.js BFF using internal API key
**File**: `maternal-app-backend/src/common/guards/internal-api-key.guard.ts` (new)
```typescript
import { Injectable, CanActivate, ExecutionContext, UnauthorizedException } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
@Injectable()
export class InternalApiKeyGuard implements CanActivate {
constructor(private configService: ConfigService) {}
canActivate(context: ExecutionContext): boolean {
const request = context.switchToHttp().getRequest();
const apiKey = request.headers['x-internal-api-key'];
const expectedKey = this.configService.get('INTERNAL_API_KEY');
if (!expectedKey) {
// If not configured, allow (development mode)
return true;
}
if (apiKey !== expectedKey) {
throw new UnauthorizedException('Invalid internal API key');
}
return true;
}
}
```
**Usage** (apply to all controllers):
```typescript
import { Controller, UseGuards } from '@nestjs/common';
import { InternalApiKeyGuard } from '../common/guards/internal-api-key.guard';
@Controller('api/v1/children')
@UseGuards(InternalApiKeyGuard) // Add this to all controllers
export class ChildrenController {
// ...
}
```
---
### Step 4: Configure Mobile App Direct Access
**Goal**: Mobile apps bypass BFF and call backend directly with API key + JWT
**Backend Configuration**:
```typescript
// app.module.ts
app.enableCors({
origin: [
'http://localhost:3030', // Next.js dev
'https://maternal.noru1.ro', // Production web
'capacitor://localhost', // iOS mobile
'http://localhost', // Android mobile
'ionic://localhost', // Ionic mobile
],
credentials: true,
});
```
**Mobile App Configuration** (future):
```typescript
// mobile-app/src/config/api.ts
const API_CONFIG = {
baseUrl: 'https://api.maternal.noru1.ro', // Direct backend access
graphqlUrl: 'https://api.maternal.noru1.ro/graphql',
wsUrl: 'wss://api.maternal.noru1.ro',
headers: {
'X-API-Key': process.env.MOBILE_API_KEY, // Different from internal key
},
};
```
---
### Step 5: Nginx Configuration for Production
**Goal**: Use Nginx as reverse proxy for SSL termination and basic security
**File**: `/etc/nginx/sites-available/maternal-app`
```nginx
# Upstream backends
upstream nextjs_backend {
server 127.0.0.1:3030;
}
upstream nestjs_backend {
server 127.0.0.1:3020;
}
# Redirect HTTP to HTTPS
server {
listen 80;
server_name maternal.noru1.ro;
return 301 https://$server_name$request_uri;
}
# Main web application (Next.js)
server {
listen 443 ssl http2;
server_name maternal.noru1.ro;
ssl_certificate /etc/letsencrypt/live/maternal.noru1.ro/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/maternal.noru1.ro/privkey.pem;
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# Rate limiting
limit_req_zone $binary_remote_addr zone=web_limit:10m rate=100r/m;
limit_req zone=web_limit burst=20 nodelay;
location / {
proxy_pass http://nextjs_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
# API backend (for mobile apps only - optional)
server {
listen 443 ssl http2;
server_name api.maternal.noru1.ro;
ssl_certificate /etc/letsencrypt/live/api.maternal.noru1.ro/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.maternal.noru1.ro/privkey.pem;
# Stricter rate limiting for API
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=60r/m;
limit_req zone=api_limit burst=10 nodelay;
# Only allow mobile app user agents (optional)
if ($http_user_agent !~* (Maternal-iOS|Maternal-Android|curl)) {
return 403;
}
location / {
proxy_pass http://nestjs_backend;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# WebSocket support
location /ws {
proxy_pass http://nestjs_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
}
```
---
## 🔒 Security Enhancements
### 1. API Key Management
**Environment Variables**:
```bash
# Backend (.env.production)
INTERNAL_API_KEY=<strong-random-key-for-nextjs-bff>
MOBILE_API_KEY=<different-key-for-mobile-apps>
# Next.js (.env.local)
INTERNAL_API_KEY=<same-as-backend-internal-key>
BACKEND_API_URL=http://localhost:3020 # or internal network IP
```
**Generation**:
```bash
# Generate secure API keys
openssl rand -base64 32
```
---
### 2. Rate Limiting Strategy
| Client Type | Rate Limit | Enforcement |
|-------------|------------|-------------|
| Web (BFF) | 100 req/min per IP | Nginx |
| Mobile (Direct) | 60 req/min per API key | Nginx + NestJS |
| GraphQL | 30 queries/min | NestJS middleware |
| WebSocket | 10 connections per user | NestJS gateway |
**Implementation** (NestJS):
```typescript
// src/common/middleware/rate-limit.middleware.ts
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';
import { Redis } from 'ioredis';
@Injectable()
export class ApiKeyRateLimitMiddleware implements NestMiddleware {
constructor(private redis: Redis) {}
async use(req: Request, res: Response, next: NextFunction) {
const apiKey = req.headers['x-api-key'];
if (!apiKey) {
return next();
}
const key = `rate_limit:api_key:${apiKey}`;
const count = await this.redis.incr(key);
if (count === 1) {
await this.redis.expire(key, 60); // 1 minute window
}
if (count > 60) {
return res.status(429).json({
error: 'Rate limit exceeded',
retryAfter: await this.redis.ttl(key),
});
}
next();
}
}
```
---
### 3. CORS Configuration
**Strict CORS for Production**:
```typescript
// main.ts
app.enableCors({
origin: (origin, callback) => {
const allowedOrigins = [
'https://maternal.noru1.ro',
'https://maternal-web.noru1.ro',
];
// Allow mobile apps (check user agent)
if (!origin || allowedOrigins.includes(origin)) {
callback(null, true);
} else if (origin.includes('capacitor://')) {
callback(null, true); // Ionic/Capacitor
} else {
callback(new Error('Not allowed by CORS'));
}
},
credentials: true,
methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
allowedHeaders: [
'Content-Type',
'Authorization',
'X-API-Key',
'X-Internal-API-Key',
],
});
```
---
## 📱 Mobile App Integration
### React Native / Expo Configuration
```typescript
// mobile-app/src/services/api.ts
import axios from 'axios';
import Constants from 'expo-constants';
const API_CONFIG = {
baseURL: Constants.expoConfig?.extra?.apiUrl || 'https://api.maternal.noru1.ro',
headers: {
'X-API-Key': Constants.expoConfig?.extra?.apiKey,
'User-Agent': `Maternal-${Platform.OS}/${Constants.expoConfig?.version}`,
},
};
const apiClient = axios.create(API_CONFIG);
// Add JWT token to requests
apiClient.interceptors.request.use((config) => {
const token = getAuthToken(); // From AsyncStorage
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
```
**WebSocket Connection** (mobile):
```typescript
import io from 'socket.io-client';
const socket = io('wss://api.maternal.noru1.ro', {
auth: {
token: getAuthToken(),
},
transports: ['websocket'],
reconnection: true,
reconnectionAttempts: 5,
});
```
---
## 🔍 Monitoring & Logging
### 1. Request Logging (Nginx)
```nginx
log_format api_log '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'api_key=$http_x_api_key '
'request_time=$request_time';
access_log /var/log/nginx/maternal_api_access.log api_log;
```
### 2. Backend Request Tracking
```typescript
// src/common/middleware/request-logger.middleware.ts
import { Injectable, NestMiddleware, Logger } from '@nestjs/common';
@Injectable()
export class RequestLoggerMiddleware implements NestMiddleware {
private logger = new Logger('HTTP');
use(req: Request, res: Response, next: NextFunction) {
const { method, originalUrl, headers } = req;
const userAgent = headers['user-agent'];
const apiKey = headers['x-api-key'];
const isInternal = headers['x-internal-api-key'] ? 'internal' : 'external';
const start = Date.now();
res.on('finish', () => {
const { statusCode } = res;
const duration = Date.now() - start;
this.logger.log(
`${method} ${originalUrl} ${statusCode} ${duration}ms - ${isInternal} - ${apiKey?.substring(0, 8)}...`
);
});
next();
}
}
```
---
## 🚀 Deployment Strategy
### Phase 1: MVP Deployment (Week 1-2)
**Week 1**:
- [x] Create Next.js API proxy routes
- [x] Update frontend to use BFF
- [x] Add internal API key guard to backend
- [x] Test web app with new architecture
**Week 2**:
- [x] Configure Nginx reverse proxy
- [x] Set up SSL certificates
- [x] Deploy to production
- [x] Monitor and fix issues
### Phase 2: Mobile App Support (Week 3-4)
**Week 3**:
- [ ] Create mobile API keys
- [ ] Configure CORS for mobile
- [ ] Set up mobile-specific rate limits
- [ ] Test with React Native/Expo
**Week 4**:
- [ ] Add mobile user agent detection
- [ ] Implement mobile analytics
- [ ] Load testing with mobile traffic
- [ ] Documentation for mobile devs
### Phase 3: Kong Gateway (Month 2-3)
**Month 2**:
- [ ] Set up Kong API Gateway
- [ ] Configure plugins (rate limit, JWT, logging)
- [ ] Migrate Next.js BFF to Kong routes
- [ ] Test parallel deployment
**Month 3**:
- [ ] Full cutover to Kong
- [ ] Remove Next.js BFF (optional)
- [ ] Advanced features (caching, GraphQL federation)
- [ ] Performance optimization
---
## 📊 Performance Considerations
### Latency Impact
| Architecture | Latency | Notes |
|--------------|---------|-------|
| Direct Backend | 50-100ms | Current (baseline) |
| Next.js BFF | +20-40ms | Acceptable for web |
| Kong Gateway | +10-20ms | Production-optimized |
### Caching Strategy
**Next.js Edge Caching**:
```typescript
// app/api/proxy/[...path]/route.ts
export const revalidate = 60; // Cache for 60 seconds
// Or per-route
if (path.startsWith('children')) {
return NextResponse.json(data, {
headers: {
'Cache-Control': 'public, s-maxage=300, stale-while-revalidate=600',
},
});
}
```
**Redis Caching** (backend):
```typescript
// Already implemented in backend
@UseInterceptors(CacheInterceptor)
@CacheTTL(300)
async getChildren() {
// ...
}
```
---
## ✅ Acceptance Criteria
### Security
- [ ] Backend not directly accessible from browser (except WebSocket for now)
- [ ] Internal API key required for BFF → Backend
- [ ] Mobile API key required for mobile → Backend
- [ ] Rate limiting enforced at Nginx and NestJS levels
- [ ] CORS configured for web and mobile origins
- [ ] SSL/TLS for all external connections
### Functionality
- [ ] Web app works through BFF without code changes to components
- [ ] GraphQL queries work through proxy
- [ ] WebSocket connections remain stable
- [ ] Mobile apps can connect directly to backend
- [ ] Real-time sync works across web and mobile
### Performance
- [ ] Latency increase < 50ms for BFF
- [ ] No degradation in WebSocket performance
- [ ] API response times within SLA (<200ms p95)
### Monitoring
- [ ] Request logs include API key and source
- [ ] Rate limit violations logged
- [ ] Error tracking for proxy failures
- [ ] Metrics dashboard shows BFF vs direct traffic
---
## 🔧 Troubleshooting
### Common Issues
**1. WebSocket Connections Failing**
- **Symptom**: Socket.io connection refused
- **Fix**: Ensure WebSocket endpoint bypasses BFF (direct backend connection)
- **Config**: Update `NEXT_PUBLIC_WS_URL` to backend URL
**2. CORS Errors on Mobile**
- **Symptom**: OPTIONS preflight fails
- **Fix**: Add mobile origins to CORS whitelist
- **Config**: Check `capacitor://localhost` is allowed
**3. Rate Limiting Too Aggressive**
- **Symptom**: 429 errors during normal usage
- **Fix**: Adjust Nginx `limit_req` or NestJS throttler
- **Config**: Increase burst size or rate
**4. GraphQL Subscriptions Not Working**
- **Symptom**: Subscriptions disconnect immediately
- **Fix**: GraphQL subscriptions need WebSocket, can't go through HTTP proxy
- **Solution**: Use Apollo Client with split link (HTTP for queries, WS for subscriptions)
---
## 📚 References
- [Next.js API Routes Documentation](https://nextjs.org/docs/api-routes/introduction)
- [Kong API Gateway](https://konghq.com/products/kong-gateway)
- [Nginx Reverse Proxy Guide](https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/)
- [NestJS Guards](https://docs.nestjs.com/guards)
- [Socket.io CORS Configuration](https://socket.io/docs/v4/handling-cors/)
---
**Last Updated**: October 3, 2025
**Review Date**: Post-MVP Launch
**Owner**: Backend Team

View File

@@ -1,251 +0,0 @@
# Database Migrations Consolidation
**Generated**: October 6, 2025
**Purpose**: Consolidated database migration strategy for fresh installs and upgrades
## Current Migration Issues
### Duplicate Version Numbers
The following version numbers have multiple migration files:
- **V008**: 4 different migrations
- V008_create_photos.sql
- V008_create_data_deletion_requests.sql
- V008_add_user_photo_url.sql
- V008_add_eula_acceptance.sql
- **V009**: 3 different migrations
- V009_create_activity_partitions.sql
- V009_add_photo_alt_text.sql
- V009_add_performance_indexes.sql
- **V010**: 3 different migrations
- V010_create_ai_conversations.sql
- V010_add_mfa_fields.sql
- V010_create_user_preferences.sql
- **V011**: 2 different migrations
- V011_create_password_reset_tokens.sql
- V011_add_webauthn_credentials.sql
## Consolidated Migration Order
### Phase 1: Core Authentication & Users
```
V001_create_core_auth.sql
V002_create_family_structure.sql
V003_create_refresh_tokens.sql
```
### Phase 2: Activity Tracking
```
V004_create_activity_tracking.sql
V005_add_user_preferences.sql
V006_create_audit_log.sql
```
### Phase 3: Communications & Media
```
V007_create_notifications.sql
V008_create_photos.sql
```
### Phase 4: User Profile Enhancements
```
V009_add_user_photo_url.sql
V010_add_photo_alt_text.sql
V011_add_eula_acceptance.sql
```
### Phase 5: Security Enhancements
```
V012_add_mfa_fields.sql
V013_add_webauthn_credentials.sql
V014_create_password_reset_tokens.sql
```
### Phase 6: AI Features
```
V015_create_ai_conversations.sql
V016_create_voice_feedback.sql
V017_create_conversation_embeddings.sql
```
### Phase 7: Compliance & Privacy
```
V018_create_data_deletion_requests.sql
V019_create_deletion_requests.sql
V020_add_coppa_compliance.sql
```
### Phase 8: Performance & Preferences
```
V021_create_activity_partitions.sql
V022_add_performance_indexes.sql
V023_create_user_preferences.sql
```
### Phase 9: Additional Features
```
V024_add_medicine_activity_types.sql
V025_add_child_display_preferences.sql
V026_create_multi_child_preferences.sql
V027_add_activity_bulk_operations.sql
```
## Renaming Strategy
To fix the duplicate version numbers, here's the renaming plan:
| Old Name | New Name | Purpose |
|----------|----------|---------|
| V001_create_core_auth.sql | V001_create_core_auth.sql | No change |
| V002_create_family_structure.sql | V002_create_family_structure.sql | No change |
| V003_create_refresh_tokens.sql | V003_create_refresh_tokens.sql | No change |
| V004_create_activity_tracking.sql | V004_create_activity_tracking.sql | No change |
| V005_add_user_preferences.sql | V005_add_user_preferences.sql | No change |
| V006_create_audit_log.sql | V006_create_audit_log.sql | No change |
| V007_create_notifications.sql | V007_create_notifications.sql | No change |
| V008_create_photos.sql | V008_create_photos.sql | Keep first V008 |
| V008_add_user_photo_url.sql | V009_add_user_photo_url.sql | Rename |
| V009_add_photo_alt_text.sql | V010_add_photo_alt_text.sql | Rename |
| V008_add_eula_acceptance.sql | V011_add_eula_acceptance.sql | Rename |
| V010_add_mfa_fields.sql | V012_add_mfa_fields.sql | Rename |
| V011_add_webauthn_credentials.sql | V013_add_webauthn_credentials.sql | Rename |
| V011_create_password_reset_tokens.sql | V014_create_password_reset_tokens.sql | Rename |
| V010_create_ai_conversations.sql | V015_create_ai_conversations.sql | Rename |
| V012_create_voice_feedback.sql | V016_create_voice_feedback.sql | Rename |
| V014_create_conversation_embeddings.sql | V017_create_conversation_embeddings.sql | Rename |
| V008_create_data_deletion_requests.sql | V018_create_data_deletion_requests.sql | Rename |
| V015_create_deletion_requests.sql | V019_create_deletion_requests.sql | Rename (duplicate?) |
| V016_add_coppa_compliance.sql | V020_add_coppa_compliance.sql | Rename |
| V009_create_activity_partitions.sql | V021_create_activity_partitions.sql | Rename |
| V009_add_performance_indexes.sql | V022_add_performance_indexes.sql | Rename |
| V010_create_user_preferences.sql | V023_create_user_preferences.sql | Rename |
| V013_add_medicine_activity_types.sql | V024_add_medicine_activity_types.sql | Rename |
| V017_add_child_display_preferences.sql | V025_add_child_display_preferences.sql | Rename |
| V018_create_multi_child_preferences.sql | V026_create_multi_child_preferences.sql | Rename |
| V019_add_activity_bulk_operations.sql | V027_add_activity_bulk_operations.sql | Rename |
## Master Migration Script
For fresh installations, we need a single script that runs all migrations in order:
```bash
#!/bin/bash
# master-migration.sh - Run all migrations for fresh install
DATABASE_NAME="${DATABASE_NAME:-parentflow_production}"
DATABASE_USER="${DATABASE_USER:-parentflow_user}"
DATABASE_HOST="${DATABASE_HOST:-localhost}"
DATABASE_PORT="${DATABASE_PORT:-5432}"
MIGRATION_DIR="./src/database/migrations"
# Array of migrations in correct order
MIGRATIONS=(
"V001_create_core_auth.sql"
"V002_create_family_structure.sql"
"V003_create_refresh_tokens.sql"
"V004_create_activity_tracking.sql"
"V005_add_user_preferences.sql"
"V006_create_audit_log.sql"
"V007_create_notifications.sql"
"V008_create_photos.sql"
"V009_add_user_photo_url.sql"
"V010_add_photo_alt_text.sql"
"V011_add_eula_acceptance.sql"
"V012_add_mfa_fields.sql"
"V013_add_webauthn_credentials.sql"
"V014_create_password_reset_tokens.sql"
"V015_create_ai_conversations.sql"
"V016_create_voice_feedback.sql"
"V017_create_conversation_embeddings.sql"
"V018_create_data_deletion_requests.sql"
"V019_create_deletion_requests.sql"
"V020_add_coppa_compliance.sql"
"V021_create_activity_partitions.sql"
"V022_add_performance_indexes.sql"
"V023_create_user_preferences.sql"
"V024_add_medicine_activity_types.sql"
"V025_add_child_display_preferences.sql"
"V026_create_multi_child_preferences.sql"
"V027_add_activity_bulk_operations.sql"
)
echo "Starting database migration..."
echo "Database: $DATABASE_NAME@$DATABASE_HOST:$DATABASE_PORT"
for migration in "${MIGRATIONS[@]}"; do
echo "Running migration: $migration"
psql -h "$DATABASE_HOST" -p "$DATABASE_PORT" -U "$DATABASE_USER" -d "$DATABASE_NAME" -f "$MIGRATION_DIR/$migration"
if [ $? -ne 0 ]; then
echo "ERROR: Migration $migration failed!"
exit 1
fi
echo "✓ Migration $migration completed"
done
echo "All migrations completed successfully!"
```
## Migration Tracking Table
Create a migration tracking table to record which migrations have been applied:
```sql
-- V000_create_migration_tracking.sql
CREATE TABLE IF NOT EXISTS schema_migrations (
version VARCHAR(10) PRIMARY KEY,
filename VARCHAR(255) NOT NULL,
applied_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
checksum VARCHAR(64),
description TEXT
);
-- Index for quick lookup
CREATE INDEX idx_schema_migrations_applied_at ON schema_migrations(applied_at);
```
## Action Items
1. **Rename duplicate migration files** to use sequential versioning
2. **Create migration tracking table** (V000_create_migration_tracking.sql)
3. **Create master migration script** for fresh installs
4. **Update TypeORM configuration** to use renamed migrations
5. **Test migration sequence** on fresh database
6. **Document rollback procedures** for each migration
## Rollback Strategy
Each migration should have a corresponding rollback script:
```
migrations/
V001_create_core_auth.sql
V001_create_core_auth.rollback.sql
V002_create_family_structure.sql
V002_create_family_structure.rollback.sql
...
```
## Notes for Developers
1. Always use sequential version numbers (V001, V002, etc.)
2. Never reuse version numbers
3. Include descriptive names after version number
4. Always test migrations on a copy of production data
5. Include both upgrade and rollback scripts
6. Document any data transformations
7. Check for dependencies between migrations
## Migration Validation Checklist
Before running migrations on production:
- [ ] All migrations tested on staging environment
- [ ] Backup of production database taken
- [ ] Rollback scripts prepared and tested
- [ ] Migration order verified
- [ ] No duplicate version numbers
- [ ] All foreign key constraints validated
- [ ] Indexes created for performance
- [ ] Data migration scripts tested (if applicable)
- [ ] Application code compatible with schema changes
- [ ] Monitoring alerts configured for migration issues

File diff suppressed because it is too large Load Diff

View File

@@ -1,670 +0,0 @@
# Accessibility Implementation Plan - Maternal App
**Created**: October 2, 2025
**Target**: WCAG 2.1 AA Compliance
**Priority**: CRITICAL (Launch Blocker)
---
## Executive Summary
This document outlines the comprehensive accessibility implementation plan to achieve WCAG 2.1 AA compliance for the Maternal App. Accessibility is a **critical launch requirement** for legal compliance (ADA, Section 508) and to ensure the app is usable by all parents, including those with disabilities.
**Current Status**: No accessibility implementation detected
**Target**: Full WCAG 2.1 AA compliance
**Timeline**: 2 weeks (Phases 1-3)
---
## Table of Contents
1. [Why Accessibility Matters](#why-accessibility-matters)
2. [WCAG 2.1 AA Requirements](#wcag-21-aa-requirements)
3. [Current State Assessment](#current-state-assessment)
4. [Implementation Phases](#implementation-phases)
5. [Technical Requirements](#technical-requirements)
6. [Testing Strategy](#testing-strategy)
7. [Success Metrics](#success-metrics)
---
## Why Accessibility Matters
### Legal Requirements
- **ADA (Americans with Disabilities Act)**: Web accessibility is legally required
- **Section 508**: Federal compliance for government users
- **WCAG 2.1 AA**: International standard for web accessibility
### User Impact
- **15% of the population** has some form of disability
- **New parents** may have temporary disabilities (sleep deprivation, holding baby)
- **Situational disabilities**: Using app in bright sunlight, noisy environments
- **Assistive technology users**: Screen readers, keyboard-only, voice control
### Business Benefits
- Larger addressable market
- Better SEO (semantic HTML)
- Improved UX for all users
- Legal risk mitigation
- Positive brand reputation
---
## WCAG 2.1 AA Requirements
### Four Core Principles (POUR)
#### 1. **Perceivable**
- Text alternatives for non-text content
- Captions and alternatives for multimedia
- Adaptable content (can be presented in different ways)
- Distinguishable (easy to see and hear)
#### 2. **Operable**
- Keyboard accessible (all functionality available via keyboard)
- Sufficient time (users have enough time to read and use content)
- Seizures and physical reactions (nothing that causes seizures)
- Navigable (users can navigate, find content, and determine where they are)
- Input modalities (make it easier to operate functionality through various inputs)
#### 3. **Understandable**
- Readable (text content is readable and understandable)
- Predictable (web pages appear and operate in predictable ways)
- Input assistance (help users avoid and correct mistakes)
#### 4. **Robust**
- Compatible (maximize compatibility with current and future user agents)
---
## Current State Assessment
### What We Have ✅
- **Material-UI (MUI)**: Built-in accessibility features
- **React 18**: Modern framework with good accessibility support
- **Semantic HTML**: Some usage of proper HTML5 elements
- **Next.js 13**: Server-side rendering for better screen reader support
### What's Missing ❌
#### **Critical Issues**
1. ❌ No ARIA labels on interactive elements
2. ❌ No keyboard navigation support
3. ❌ No focus indicators
4. ❌ No screen reader testing
5. ❌ Missing alt text on images/icons
6. ❌ Poor color contrast (not verified)
7. ❌ No skip navigation links
8. ❌ Forms lack proper labels and error messages
9. ❌ No focus management for dialogs/modals
10. ❌ No reduced motion support
#### **High Priority Issues**
- Missing landmark regions (header, nav, main, footer)
- No heading hierarchy verification
- Missing aria-live regions for dynamic content
- No keyboard shortcuts documentation
- Touch targets not verified (44x44px minimum)
---
## Implementation Phases
### **Phase 1: Foundation (Week 1, Days 1-3)** 🏗️
#### **Goal**: Establish accessibility infrastructure and fix critical keyboard/focus issues
**Tasks:**
1. **Setup Accessibility Tools** (Day 1 Morning)
- Install `eslint-plugin-jsx-a11y` (React accessibility linting)
- Install `axe-core` and `@axe-core/react` (runtime accessibility testing)
- Configure ESLint rules for accessibility
- Install `jest-axe` for automated testing
- Add accessibility check to CI/CD
2. **Keyboard Navigation** (Day 1 Afternoon - Day 2)
- Implement focus trap for modals/dialogs
- Add visible focus indicators (outline/ring)
- Create skip navigation link
- Fix tab order across all pages
- Add keyboard shortcuts for common actions
- Document keyboard navigation patterns
3. **ARIA Labels & Semantic HTML** (Day 2 - Day 3)
- Audit all interactive elements (buttons, links, inputs)
- Add aria-label/aria-labelledby where needed
- Fix heading hierarchy (h1 → h2 → h3)
- Add landmark regions (header, nav, main, footer)
- Convert icon-only buttons to have text alternatives
- Add aria-describedby for form hints
4. **Focus Management** (Day 3)
- Implement focus management for route changes
- Focus first heading on page load
- Trap focus in modals/dialogs
- Return focus when closing modals
- Manage focus for toast notifications
**Deliverables:**
- ESLint accessibility rules configured
- Axe-core integrated into dev environment
- All pages keyboard navigable
- Focus indicators visible
- Skip navigation link added
---
### **Phase 2: Content & Forms (Week 1, Days 4-5)** 📝
#### **Goal**: Make all content accessible and improve form usability
**Tasks:**
1. **Alternative Text** (Day 4 Morning)
- Audit all images for alt text
- Add descriptive alt text to photos
- Mark decorative images as `alt=""`
- Add aria-label to icon buttons
- Document icon meanings
2. **Form Accessibility** (Day 4 Afternoon - Day 5 Morning)
- Add explicit labels to all inputs
- Associate labels with inputs (htmlFor/id)
- Add aria-required to required fields
- Improve error messages with aria-invalid
- Add aria-describedby for help text
- Group related inputs with fieldset/legend
- Add autocomplete attributes
3. **Color Contrast** (Day 5 Morning)
- Audit color contrast ratios (WCAG AA: 4.5:1 for text, 3:1 for large text)
- Fix low-contrast text
- Ensure error states don't rely on color alone
- Add patterns/icons to supplement color coding
4. **Live Regions** (Day 5 Afternoon)
- Add aria-live to toast notifications
- Add aria-live to loading states
- Add aria-live to activity feed updates
- Add status messages for async operations
**Deliverables:**
- All images have appropriate alt text
- All forms fully accessible
- Color contrast meets WCAG AA
- Live regions for dynamic content
---
### **Phase 3: Testing & Polish (Week 2, Days 1-3)** ✅
#### **Goal**: Comprehensive testing and documentation
**Tasks:**
1. **Automated Testing** (Day 1)
- Write jest-axe tests for all pages
- Add axe-core checks to E2E tests
- Run Lighthouse accessibility audits
- Fix all automated test failures
- Add accessibility tests to CI/CD
2. **Screen Reader Testing** (Day 2)
- Test with NVDA (Windows)
- Test with JAWS (Windows)
- Test with VoiceOver (macOS/iOS)
- Test with TalkBack (Android)
- Document screen reader issues
- Fix critical screen reader bugs
3. **Manual Testing** (Day 2-3)
- Test all pages with keyboard only (no mouse)
- Test with browser zoom (up to 200%)
- Test with high contrast mode
- Test with reduced motion
- Test with different viewport sizes
- Test all user flows
4. **Documentation** (Day 3)
- Create accessibility statement page
- Document keyboard shortcuts
- Add ARIA patterns guide for developers
- Create accessibility testing checklist
- Document known issues (if any)
**Deliverables:**
- Automated accessibility tests passing
- Screen reader testing complete
- Manual testing checklist complete
- Accessibility documentation published
---
### **Phase 4: Advanced Features (Week 2, Days 4-5)** 🚀
#### **Goal**: Enhanced accessibility features
**Tasks:**
1. **Reduced Motion Support** (Day 4 Morning)
```css
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
```
- Detect `prefers-reduced-motion`
- Disable animations for users who prefer reduced motion
- Keep essential motion (loading indicators)
2. **Text Scaling** (Day 4 Afternoon)
- Test with browser text zoom up to 200%
- Use relative units (rem, em) instead of px
- Ensure layout doesn't break at 200% zoom
- Test with browser zoom (page zoom)
3. **Touch Target Sizes** (Day 5 Morning)
- Audit all interactive elements
- Ensure minimum 44x44px (iOS) / 48x48dp (Android)
- Add padding to small targets
- Increase spacing between adjacent targets
4. **Additional Enhancements** (Day 5 Afternoon)
- Add high contrast mode support
- Add visual focus indicators for mouse users
- Implement focus-within for nested focus
- Add aria-current for navigation
**Deliverables:**
- Reduced motion support implemented
- Text scaling verified up to 200%
- Touch targets meet minimum sizes
- Enhanced accessibility features live
---
## Technical Requirements
### **1. Dependencies to Install**
```bash
# Linting and Testing
npm install --save-dev eslint-plugin-jsx-a11y
npm install --save-dev jest-axe
npm install --save-dev @axe-core/react
# Runtime Testing
npm install --save @axe-core/react
# Focus Management
npm install react-focus-lock focus-trap-react
# Reduced Motion Hook
npm install framer-motion # Already installed, use useReducedMotion
```
### **2. ESLint Configuration**
Add to `.eslintrc.json`:
```json
{
"extends": [
"plugin:jsx-a11y/recommended"
],
"plugins": ["jsx-a11y"],
"rules": {
"jsx-a11y/anchor-is-valid": "error",
"jsx-a11y/aria-props": "error",
"jsx-a11y/aria-proptypes": "error",
"jsx-a11y/aria-unsupported-elements": "error",
"jsx-a11y/heading-has-content": "error",
"jsx-a11y/img-redundant-alt": "error",
"jsx-a11y/label-has-associated-control": "error",
"jsx-a11y/no-autofocus": "warn",
"jsx-a11y/no-static-element-interactions": "error"
}
}
```
### **3. Axe-Core Integration (Development)**
Create `components/providers/AxeProvider.tsx`:
```typescript
'use client';
import React, { useEffect } from 'react';
export function AxeProvider({ children }: { children: React.ReactNode }) {
useEffect(() => {
if (process.env.NODE_ENV === 'development') {
import('@axe-core/react').then((axe) => {
axe.default(React, require('react-dom'), 1000);
});
}
}, []);
return <>{children}</>;
}
```
### **4. Focus Visible Styles**
Add to `globals.css`:
```css
/* Focus indicators */
*:focus {
outline: 2px solid #FF8B7D; /* Coral from design system */
outline-offset: 2px;
}
/* Focus visible (keyboard only) */
*:focus:not(:focus-visible) {
outline: none;
}
*:focus-visible {
outline: 2px solid #FF8B7D;
outline-offset: 2px;
}
/* Skip link */
.skip-link {
position: absolute;
top: -40px;
left: 0;
background: #000;
color: white;
padding: 8px;
text-decoration: none;
z-index: 100;
}
.skip-link:focus {
top: 0;
}
```
### **5. Accessibility Utilities**
Create `lib/accessibility.ts`:
```typescript
/**
* Accessibility utility functions
*/
// Announce to screen readers
export function announceToScreenReader(message: string, priority: 'polite' | 'assertive' = 'polite') {
const announcement = document.createElement('div');
announcement.setAttribute('role', 'status');
announcement.setAttribute('aria-live', priority);
announcement.setAttribute('aria-atomic', 'true');
announcement.className = 'sr-only';
announcement.textContent = message;
document.body.appendChild(announcement);
setTimeout(() => {
document.body.removeChild(announcement);
}, 1000);
}
// Check if reduced motion is preferred
export function prefersReducedMotion(): boolean {
return window.matchMedia('(prefers-reduced-motion: reduce)').matches;
}
// Get contrast ratio between two colors
export function getContrastRatio(color1: string, color2: string): number {
// Implementation using relative luminance formula
// WCAG requires 4.5:1 for normal text, 3:1 for large text
}
// Trap focus within an element
export function trapFocus(element: HTMLElement) {
const focusableElements = element.querySelectorAll(
'a[href], button, textarea, input, select, [tabindex]:not([tabindex="-1"])'
);
const firstElement = focusableElements[0] as HTMLElement;
const lastElement = focusableElements[focusableElements.length - 1] as HTMLElement;
element.addEventListener('keydown', (e) => {
if (e.key === 'Tab') {
if (e.shiftKey && document.activeElement === firstElement) {
e.preventDefault();
lastElement.focus();
} else if (!e.shiftKey && document.activeElement === lastElement) {
e.preventDefault();
firstElement.focus();
}
}
});
}
```
---
## Testing Strategy
### **1. Automated Testing**
#### **ESLint (Static Analysis)**
```bash
npm run lint # Check for accessibility violations
```
#### **jest-axe (Unit Tests)**
```typescript
import { render } from '@testing-library/react';
import { axe, toHaveNoViolations } from 'jest-axe';
expect.extend(toHaveNoViolations);
test('Dashboard should be accessible', async () => {
const { container } = render(<Dashboard />);
const results = await axe(container);
expect(results).toHaveNoViolations();
});
```
#### **Playwright (E2E Tests)**
```typescript
test('should pass accessibility audit', async ({ page }) => {
await page.goto('/dashboard');
const accessibilityScanResults = await page.evaluate(async () => {
const axe = await import('axe-core');
return await axe.run();
});
expect(accessibilityScanResults.violations).toEqual([]);
});
```
#### **Lighthouse CI**
```bash
npm install --save-dev @lhci/cli
lhci autorun --collect.url=http://localhost:3000 --assert.preset=lighthouse:accessibility
```
### **2. Manual Testing Checklist**
#### **Keyboard Navigation**
- [ ] All interactive elements are keyboard accessible
- [ ] Tab order is logical
- [ ] Focus indicators are visible
- [ ] Skip navigation link works
- [ ] No keyboard traps
- [ ] Escape key closes modals
- [ ] Enter/Space activate buttons
#### **Screen Reader Testing**
- [ ] Page title is announced
- [ ] Headings are in logical order
- [ ] Form labels are announced
- [ ] Error messages are announced
- [ ] Status updates are announced
- [ ] Images have alt text
- [ ] Links have descriptive text
#### **Visual Testing**
- [ ] Color contrast meets 4.5:1 (normal text)
- [ ] Color contrast meets 3:1 (large text, 18pt+)
- [ ] Content readable at 200% zoom
- [ ] No horizontal scrolling at 320px width
- [ ] Touch targets are 44x44px minimum
#### **Assistive Technology**
- [ ] Works with NVDA (Windows)
- [ ] Works with JAWS (Windows)
- [ ] Works with VoiceOver (Mac/iOS)
- [ ] Works with TalkBack (Android)
- [ ] Works with Dragon NaturallySpeaking (voice control)
- [ ] Works with browser zoom
### **3. Browser Testing Matrix**
| Browser | Screen Reader | Platform | Status |
|---------|---------------|----------|--------|
| Chrome | NVDA | Windows | TODO |
| Firefox | NVDA | Windows | TODO |
| Edge | JAWS | Windows | TODO |
| Safari | VoiceOver | macOS | TODO |
| Safari | VoiceOver | iOS | TODO |
| Chrome | TalkBack | Android | TODO |
---
## Success Metrics
### **Quantitative Metrics**
1. **Lighthouse Accessibility Score**: 100/100 ✅
2. **Axe-core Violations**: 0 critical, 0 serious ✅
3. **ESLint jsx-a11y Errors**: 0 ✅
4. **Color Contrast**: 100% WCAG AA compliant ✅
5. **Keyboard Navigation**: 100% of features accessible ✅
### **Qualitative Metrics**
1. **Screen Reader Testing**: All critical user flows pass ✅
2. **User Testing**: Test with 3-5 users with disabilities ✅
3. **WCAG 2.1 AA Audit**: External audit (optional but recommended) ✅
### **Key User Flows to Test**
1.**Sign Up / Log In**
- Keyboard accessible
- Error messages announced
- Form labels clear
2.**Add Activity (Feeding/Sleep/Diaper)**
- Voice input accessible
- Form fully keyboard accessible
- Success message announced
3.**View Dashboard**
- Stats cards readable
- Charts have text alternatives
- Navigation clear
4.**AI Assistant Chat**
- Chat input keyboard accessible
- Responses announced to screen reader
- Conversation history navigable
5.**Settings & Account**
- All settings keyboard accessible
- Toggle buttons have clear states
- Dialogs trap focus properly
---
## Priority Order (Critical Path)
### **Day 1 (Must Have)**
1. ESLint jsx-a11y setup
2. Visible focus indicators
3. Skip navigation link
4. Basic ARIA labels on buttons/links
### **Days 2-3 (Critical)**
5. Keyboard navigation for all pages
6. Focus management for modals
7. Form labels and error messages
8. Heading hierarchy fixes
### **Days 4-5 (High Priority)**
9. Alt text for all images
10. Color contrast fixes
11. Live regions for dynamic content
12. Automated tests (jest-axe)
### **Week 2 (Testing & Polish)**
13. Screen reader testing
14. Manual keyboard testing
15. Reduced motion support
16. Documentation
---
## Risk Mitigation
### **Potential Risks**
1. **Risk**: Breaking existing functionality
- **Mitigation**: Comprehensive testing after each change
2. **Risk**: Time overrun
- **Mitigation**: Focus on critical items first (Days 1-3)
3. **Risk**: Lack of screen reader expertise
- **Mitigation**: Use automated tools, watch video tutorials, hire consultant
4. **Risk**: Design conflicts (e.g., focus indicators affect design)
- **Mitigation**: Work with design to create accessible alternatives
---
## Resources
### **Tools**
- [Axe DevTools Browser Extension](https://www.deque.com/axe/devtools/)
- [WAVE Browser Extension](https://wave.webaim.org/extension/)
- [Color Contrast Analyzer](https://www.tpgi.com/color-contrast-checker/)
- [Lighthouse](https://developers.google.com/web/tools/lighthouse)
### **Documentation**
- [WCAG 2.1 Guidelines](https://www.w3.org/WAI/WCAG21/quickref/)
- [MDN Accessibility](https://developer.mozilla.org/en-US/docs/Web/Accessibility)
- [A11y Project Checklist](https://www.a11yproject.com/checklist/)
- [ARIA Authoring Practices](https://www.w3.org/WAI/ARIA/apg/)
### **Screen Readers**
- [NVDA (Free, Windows)](https://www.nvaccess.org/)
- [JAWS (Trial, Windows)](https://www.freedomscientific.com/products/software/jaws/)
- VoiceOver (Built-in, macOS/iOS)
- TalkBack (Built-in, Android)
---
## Next Steps
1.**Review and approve this plan**
2. 🔄 **Start Phase 1, Day 1**: Install accessibility tools
3. 🔄 **Daily standups**: Review progress, adjust as needed
4. 🔄 **Test continuously**: Don't wait until the end
---
**Document Owner**: Development Team
**Stakeholders**: Product, Design, QA, Legal
**Review Cadence**: Daily during implementation, weekly post-launch
**Let's make the Maternal App accessible to ALL parents!** 🌟

View File

@@ -1,461 +0,0 @@
# Accessibility Implementation Progress
**Last Updated**: 2025-10-02
**Status**: Phase 1 Complete ✅ (Days 1-3)
**Target**: WCAG 2.1 AA Compliance
---
## Executive Summary
**Phase 1 Foundation (Days 1-3) - ✅ COMPLETE**
### What Was Accomplished:
-**Accessibility tools setup** - ESLint jsx-a11y, Axe-core, jest-axe
-**Skip navigation** - WCAG 2.4.1 compliance
-**ARIA labels** - 45+ ARIA attributes across 9 components
-**Keyboard navigation** - Fixed critical issues (Quick Actions), verified MUI support
-**Color contrast** - All colors meet WCAG AA 4.5:1 (tested with Axe)
-**Heading hierarchy** - Proper h1→h2 structure across all pages
-**Semantic landmarks** - header, nav, main regions
-**Focus management** - Automatic focus on route changes, screen reader announcements
### Files Created: 7
1. `.eslintrc.json` - Accessibility linting rules
2. `components/providers/AxeProvider.tsx` - Dev-time testing
3. `components/common/SkipNavigation.tsx` - Skip link
4. `lib/accessibility.ts` - Utility functions (9 functions)
5. `hooks/useFocusManagement.ts` - Focus management hooks (173 lines)
6. `components/providers/FocusManagementProvider.tsx` - Provider wrapper
7. `docs/ACCESSIBILITY_PROGRESS.md` - This document
### Files Modified: 17
- `app/layout.tsx` - AxeProvider, SkipNavigation, FocusManagementProvider, main landmark
- `app/globals.css` - 119 lines accessibility styles
- `app/page.tsx` - Quick Actions keyboard accessible, color contrast, headings
- `app/(auth)/login/page.tsx` - Password toggle aria-label, h1 heading
- `app/activities/page.tsx` - h1 heading
- `app/children/page.tsx` - h1 + h2 headings
- `app/family/page.tsx` - h1 + h2 headings
- `app/settings/page.tsx` - h1 + h2 headings
- `styles/themes/maternalTheme.ts` - Text colors (contrast)
- `components/common/EmailVerificationBanner.tsx` - Button contrast
- `components/layouts/MobileNav/MobileNav.tsx` - Header, nav landmarks
- `components/layouts/TabBar/TabBar.tsx` - Nav landmark
- `components/children/ChildDialog.tsx` - ARIA labels
- `components/family/InviteMemberDialog.tsx` - ARIA labels
- `components/children/DeleteConfirmDialog.tsx` - ARIA + alertdialog
- `components/family/RemoveMemberDialog.tsx` - ARIA + alertdialog
- `components/family/JoinFamilyDialog.tsx` - ARIA labels
- `components/auth/MFAVerificationDialog.tsx` - ARIA labels
- `components/voice/VoiceFloatingButton.tsx` - ARIA + live regions
### Metrics:
| Metric | Value |
|--------|-------|
| **Total Files Created** | 7 |
| **Total Files Modified** | 17 |
| **Lines of Code Added** | ~970+ |
| **ARIA Attributes Added** | 45+ |
| **Components Improved** | 15 |
| **WCAG Success Criteria Met** | 8 |
### WCAG 2.1 Success Criteria Addressed:
**Level A:**
-**1.3.1 Info and Relationships** - Semantic HTML, ARIA labels on dialogs
-**2.1.1 Keyboard** - All interactive elements keyboard accessible
-**2.4.1 Bypass Blocks** - Skip navigation link
-**4.1.2 Name, Role, Value** - ARIA labels, roles on interactive elements
**Level AA:**
-**1.4.3 Contrast (Minimum)** - All text meets 4.5:1 ratio (tested with Axe)
-**2.4.3 Focus Order** - Logical tab order, focus management on route changes
-**2.4.6 Headings and Labels** - Descriptive headings, proper hierarchy
-**2.4.7 Focus Visible** - CSS focus indicators with :focus-visible
---
## Overview
This document tracks progress toward full WCAG 2.1 Level AA accessibility compliance for the Maternal App. Implementation follows the phased approach outlined in `ACCESSIBILITY_IMPLEMENTATION_PLAN.md`.
---
## Phase 1: Foundation (Days 1-3)
### ✅ Day 1 - Completed
#### 1. Accessibility Tools Setup
**Installed Dependencies:**
```json
{
"devDependencies": {
"eslint-plugin-jsx-a11y": "^6.10.2",
"jest-axe": "^10.0.0",
"@axe-core/react": "^4.10.2",
"eslint-config-next": "^15.5.4"
},
"dependencies": {
"react-focus-lock": "^2.13.6",
"focus-trap-react": "^11.0.4"
}
}
```
**ESLint Configuration** (`.eslintrc.json`):
- Extended `plugin:jsx-a11y/recommended`
- Configured 18 accessibility rules:
- `jsx-a11y/anchor-is-valid`: error
- `jsx-a11y/aria-props`: error
- `jsx-a11y/aria-proptypes`: error
- `jsx-a11y/aria-unsupported-elements`: error
- `jsx-a11y/heading-has-content`: error
- `jsx-a11y/img-redundant-alt`: error
- `jsx-a11y/label-has-associated-control`: error
- `jsx-a11y/no-autofocus`: warn
- `jsx-a11y/no-static-element-interactions`: error
- `jsx-a11y/alt-text`: error
- `jsx-a11y/click-events-have-key-events`: error
- `jsx-a11y/interactive-supports-focus`: error
- `jsx-a11y/no-noninteractive-element-interactions`: error
- `jsx-a11y/no-noninteractive-tabindex`: error
- `jsx-a11y/role-has-required-aria-props`: error
- `jsx-a11y/role-supports-aria-props`: error
- `jsx-a11y/tabindex-no-positive`: error
**Development Testing** (`components/providers/AxeProvider.tsx`):
- Auto-loads `@axe-core/react` in development mode
- Logs violations to console for immediate feedback
- Configured rules: color-contrast, label, button-name, link-name
- Only runs in development to avoid production performance impact
**Accessibility Utilities** (`lib/accessibility.ts`):
- `announceToScreenReader()` - Screen reader announcements with aria-live
- `prefersReducedMotion()` - Detects user motion preferences
- `trapFocus()` - Focus trap for modals/dialogs
- `getFocusableElements()` - Query focusable elements
- `getContrastRatio()` - WCAG contrast ratio calculator
- `meetsContrastRequirements()` - AA/AAA compliance checker
- `generateA11yId()` - Unique IDs for ARIA attributes
- `isElementFocusable()` - Visibility and focusability checker
- `focusElement()` - Smart focus with scroll behavior
**Global CSS** (`app/globals.css`) - 119 lines added:
- Focus indicators: `:focus-visible` with coral outline (#FF8B7D)
- Skip navigation link with keyboard-only visibility
- Screen reader only class (`.sr-only`)
- Reduced motion support (`@media (prefers-reduced-motion: reduce)`)
- High contrast mode support
- Touch target helper class (44x44px minimum)
#### 2. Skip Navigation
**Component Created** (`components/common/SkipNavigation.tsx`):
- "Skip to main content" link for keyboard users
- Visually hidden until focused
- Smooth scroll to `#main-content`
- Meets WCAG 2.4.1 (Bypass Blocks) Level A requirement
**Root Layout Integration** (`app/layout.tsx`):
- Wrapped app with `AxeProvider` for dev-time testing
- Added `SkipNavigation` component at top of body
- Wrapped children in `<main id="main-content" tabIndex={-1}>`
- Provides skip target and programmatic focus capability
#### 3. ARIA Labels & Dialog Accessibility
**Dialogs Updated** (6 components):
1. **ChildDialog** (`components/children/ChildDialog.tsx`):
- Added `aria-labelledby="child-dialog-title"`
- Added `aria-describedby="child-dialog-description"`
- Error alerts with `role="alert"`
2. **InviteMemberDialog** (`components/family/InviteMemberDialog.tsx`):
- Added `aria-labelledby="invite-dialog-title"`
- Added `aria-describedby="invite-dialog-description"`
- Error alerts with `role="alert"`
3. **DeleteConfirmDialog** (`components/children/DeleteConfirmDialog.tsx`):
- Added `role="alertdialog"` for destructive action
- Added `aria-labelledby` and `aria-describedby`
- Warning icon with `aria-hidden="true"`
4. **RemoveMemberDialog** (`components/family/RemoveMemberDialog.tsx`):
- Added `role="alertdialog"`
- Added ARIA labels
- Warning icon with `aria-hidden="true"`
5. **JoinFamilyDialog** (`components/family/JoinFamilyDialog.tsx`):
- Added `aria-labelledby` and `aria-describedby`
- Error alerts with `role="alert"`
6. **MFAVerificationDialog** (`components/auth/MFAVerificationDialog.tsx`):
- Added `aria-labelledby` and `aria-describedby`
- Verification code input with `aria-label="Six digit verification code"`
- Loading indicator with `role="status"` and `aria-label`
- Security icon with `aria-hidden="true"`
- Error alerts with `role="alert"`
**Voice Input Accessibility** (`components/voice/VoiceFloatingButton.tsx`):
- Voice dialog with `aria-labelledby` and `aria-describedby`
- Microphone button with `aria-label` and `aria-pressed`
- Status text with `role="status"` and `aria-live="polite"`
- Classification result with `role="status"`
- Error messages with `role="alert"`
- Processing indicators with `aria-hidden="true"` on CircularProgress
- Unknown command dialog with ARIA labels
- Activity type select with `labelId` and `aria-label`
---
## ESLint Results
**Accessibility Warnings Found**: 7 instances of `jsx-a11y/no-autofocus`
**Analysis**:
- All autofocus instances are intentional and improve UX
- Used in dialogs where immediate keyboard input is expected:
- Login/register forms
- MFA verification code input
- Child creation dialog
- Family invitation dialog
- Password reset forms
- Configured as "warn" rather than "error" to allow intentional use
- Each instance provides clear context and expected behavior
**Other Linter Issues** (non-accessibility):
- 38 unescaped quote errors (cosmetic, not accessibility)
- 15 React Hook dependency warnings (functionality, not accessibility)
---
## Files Modified/Created
### Created (4 files):
1. `/root/maternal-app/maternal-web/.eslintrc.json` - ESLint config with jsx-a11y
2. `/root/maternal-app/maternal-web/components/providers/AxeProvider.tsx` - Dev-time testing
3. `/root/maternal-app/maternal-web/components/common/SkipNavigation.tsx` - Skip link
4. `/root/maternal-app/maternal-web/lib/accessibility.ts` - Utility functions
### Modified (9 files):
1. `/root/maternal-app/maternal-web/app/layout.tsx` - AxeProvider + SkipNavigation + main landmark
2. `/root/maternal-app/maternal-web/app/globals.css` - 119 lines of a11y styles
3. `/root/maternal-app/maternal-web/components/children/ChildDialog.tsx` - ARIA labels
4. `/root/maternal-app/maternal-web/components/family/InviteMemberDialog.tsx` - ARIA labels
5. `/root/maternal-app/maternal-web/components/children/DeleteConfirmDialog.tsx` - ARIA + alertdialog
6. `/root/maternal-app/maternal-web/components/family/RemoveMemberDialog.tsx` - ARIA + alertdialog
7. `/root/maternal-app/maternal-web/components/family/JoinFamilyDialog.tsx` - ARIA labels
8. `/root/maternal-app/maternal-web/components/auth/MFAVerificationDialog.tsx` - ARIA labels
9. `/root/maternal-app/maternal-web/components/voice/VoiceFloatingButton.tsx` - ARIA + live regions
### Package Dependencies:
- `/root/maternal-app/maternal-web/package.json` - Added eslint-config-next
---
## WCAG Success Criteria Addressed (So Far)
### Level A:
-**1.3.1 Info and Relationships** - Semantic HTML, ARIA labels on dialogs
-**2.1.1 Keyboard** - Material-UI components have built-in keyboard support
-**2.4.1 Bypass Blocks** - Skip navigation link implemented
-**4.1.2 Name, Role, Value** - ARIA labels, roles on interactive elements
### Level AA:
-**2.4.7 Focus Visible** - CSS focus indicators with `:focus-visible`
- 🔄 **1.4.3 Contrast (Minimum)** - Utility function created, audit pending
---
## Metrics
| Metric | Value |
|--------|-------|
| Files Created | 4 |
| Files Modified | 9 |
| Lines of Code Added | ~580 |
| ARIA Attributes Added | 45+ |
| Focus Management Improvements | 9 components |
| Accessibility Rules Configured | 18 |
| Utility Functions Created | 9 |
---
### ✅ Day 1-2 - Color Contrast & Heading Hierarchy Fixes
**User Testing with Axe**:
- Fixed password visibility button (added `aria-label`)
- Fixed missing h1 headings on login and home pages
- Fixed color contrast violations:
- Updated theme `text.secondary` color: #718096#4A5568 (7:1+ contrast)
- Fixed "Maternal" header color in MobileNav
- Fixed "Resend Email" button contrast in EmailVerificationBanner
- Updated all Quick Action card colors to WCAG AA (4.5:1 minimum)
- Fixed heading hierarchy issues:
- Changed stat numbers from h5 to div with aria-labels
- Added proper h2 headings with component prop
**Files Modified**:
- `app/(auth)/login/page.tsx` - Password toggle aria-label, h1 heading
- `app/page.tsx` - Quick Action colors, heading hierarchy, stat aria-labels
- `styles/themes/maternalTheme.ts` - Theme text colors
- `components/common/EmailVerificationBanner.tsx` - Button contrast
- `components/layouts/MobileNav/MobileNav.tsx` - Header color
---
### ✅ Day 2 - Keyboard Navigation Audit (In Progress)
**Audit Findings**:
**Navigation Components** - Good keyboard support:
- `TabBar.tsx` - MUI BottomNavigation has built-in keyboard support
- `MobileNav.tsx` - MUI Drawer and List components are keyboard accessible
- All navigation items are properly focusable with Tab key
**Dialogs & Modals** - Excellent keyboard support:
- MUI Dialog components have built-in focus trap
- Escape key to close
- Tab key cycles through dialog elements
- All 6 updated dialogs (Child, InviteMember, DeleteConfirm, RemoveMember, JoinFamily, MFAVerification)
**Voice Input** - Good keyboard support:
- VoiceFloatingButton uses MUI Fab (keyboard accessible)
- Dialog keyboard navigation works properly
**Critical Issue Fixed** - Quick Action Cards:
- **Problem**: Used `<Paper onClick={}>` which is not keyboard accessible
- **Solution**: Changed to `<Paper component="button">` with:
- `onKeyDown` handler for Enter and Space keys
- `aria-label` for screen readers
- `:focus-visible` styles with white outline
- Proper focus indicator matching hover state
- **File**: `app/page.tsx` (lines 136-173)
**List Items** - Good keyboard support:
- Activities list uses MUI ListItem components
- Properly keyboard navigable
**Keyboard Navigation Checklist**:
- [x] Audit tab order across all pages
- [x] Verify keyboard access to all interactive elements
- [x] Test modal/dialog keyboard navigation (MUI built-in)
- [x] Fix non-keyboard accessible elements (Quick Actions fixed)
- [ ] Document keyboard shortcuts for users
### ✅ Day 2-3 - Semantic HTML & Landmarks
**Landmark Regions Added**:
-`<header>` - Added to MobileNav AppBar (component="header")
-`<nav>` - Added to both navigation components:
- MobileNav Toolbar (component="nav", aria-label="Primary navigation")
- MobileNav Drawer (role="navigation", aria-label="Main menu")
- TabBar (component="nav", aria-label="Primary navigation")
-`<main>` - Already exists in root layout (app/layout.tsx)
**Heading Hierarchy Fixed**:
- ✅ All page titles changed from h4 to proper h1:
- app/page.tsx - "Welcome Back" (already fixed)
- app/(auth)/login/page.tsx - "Welcome Back" (already fixed)
- app/activities/page.tsx - "Recent Activities"
- app/children/page.tsx - "Children"
- app/family/page.tsx - "Family"
- app/settings/page.tsx - "Settings"
- ✅ All subsection headings changed from h6 to proper h2:
- app/children/page.tsx - "No children added yet"
- app/family/page.tsx - "Family Share Code", "Family Members"
- app/settings/page.tsx - "Profile Information", "Notifications", "Appearance", "Account Actions"
**Files Modified**:
- `components/layouts/MobileNav/MobileNav.tsx` - Added header, nav landmarks
- `components/layouts/TabBar/TabBar.tsx` - Added nav landmark
- `app/activities/page.tsx` - h1 heading
- `app/children/page.tsx` - h1 + h2 headings
- `app/family/page.tsx` - h1 + h2 headings
- `app/settings/page.tsx` - h1 + h2 headings
**Remaining Tasks**:
- [ ] Add ARIA labels to forms (mostly complete with existing labels)
- [ ] Add ARIA live regions for toast notifications (Snackbar already has role="alert")
- [ ] Add ARIA labels to data visualizations (charts - not yet implemented)
### ✅ Day 3 - Focus Management
**Focus Management Hook Created** (`hooks/useFocusManagement.ts`):
-`useFocusOnRouteChange()` - Automatically focuses h1 heading on page navigation
- ✅ Screen reader announcements for route changes (aria-live region)
-`useFocusTrap()` - Returns focus to previous element when modals close
-`useFocusOnNotification()` - Focuses important notifications/toasts
- ✅ Page title mapping for friendly screen reader announcements
**Provider Integration** (`components/providers/FocusManagementProvider.tsx`):
- ✅ Created client-side provider wrapper
- ✅ Integrated into root layout (app/layout.tsx)
- ✅ Automatic focus management across all pages
**Features Implemented**:
1. **Route Change Focus** - Moves focus to h1 on navigation (WCAG 2.4.3)
2. **Screen Reader Announcements** - "Navigated to [Page Name]" via aria-live
3. **Focus Restoration** - useFocusTrap hook for modals (MUI Dialogs already handle this)
4. **Notification Focus** - useFocusOnNotification hook available for important alerts
**Files Created**:
- `hooks/useFocusManagement.ts` (173 lines)
- `components/providers/FocusManagementProvider.tsx` (17 lines)
**Files Modified**:
- `app/layout.tsx` - Integrated FocusManagementProvider
**Testing Checklist**:
- [x] Focus management implemented
- [x] Route change focus working
- [x] Screen reader announcements working
- [ ] Test with NVDA (Windows)
- [ ] Test with JAWS (Windows)
- [ ] Test with VoiceOver (macOS)
- [ ] Test with TalkBack (Android)
---
## Testing Plan
### Automated Testing:
- ESLint with jsx-a11y plugin (running) ✅
- Axe DevTools in browser console (integrated) ✅
- jest-axe for unit tests (installed, pending test creation)
### Manual Testing:
- [ ] Keyboard-only navigation (no mouse)
- [ ] Screen reader testing (NVDA, JAWS, VoiceOver, TalkBack)
- [ ] High contrast mode verification
- [ ] Text scaling (200%) verification
- [ ] Reduced motion verification
### Tools to Use:
- Chrome DevTools Lighthouse
- axe DevTools browser extension
- NVDA (Windows)
- JAWS (Windows)
- VoiceOver (macOS/iOS)
- TalkBack (Android)
---
## Known Issues
1. **Autofocus warnings** - Intentional for UX, configured as warnings
2. **Color contrast** - Needs full audit with contrast checker utility
3. **Heading hierarchy** - Needs audit across all pages
4. **Landmarks** - Main landmark added to root, need page-specific landmarks
5. **Alt text** - Need to audit all images for descriptive alt text
---
## References
- WCAG 2.1 Guidelines: https://www.w3.org/WAI/WCAG21/quickref/
- Material-UI Accessibility: https://mui.com/material-ui/guides/accessibility/
- Next.js Accessibility: https://nextjs.org/docs/accessibility
- Axe DevTools: https://www.deque.com/axe/devtools/

View File

@@ -1,322 +0,0 @@
# AI Safety Implementation Summary
**Date:** October 2, 2025
**Status:** ✅ COMPLETE
**Test Coverage:** 31/31 tests passing (100%)
---
## Implementation Overview
Comprehensive AI Safety system implemented for the Maternal App to ensure safe, responsible, and helpful AI interactions for parents seeking childcare guidance.
## 1. Files Created
### Strategy & Documentation
- `AI_SAFETY_STRATEGY.md` (518 lines) - Comprehensive safety strategy with 12 sections
- `AI_SAFETY_IMPLEMENTATION_SUMMARY.md` (this file) - Implementation summary
### Backend Services
- `ai-safety.service.ts` (533 lines) - Core safety service with keyword detection
- `ai-rate-limit.service.ts` (350 lines) - Enhanced rate limiting with abuse prevention
- `ai-safety.service.spec.ts` (359 lines) - Comprehensive test suite (31 tests)
### Files Modified
- `ai.module.ts` - Added AISafetyService and AIRateLimitService to providers
- `ai.service.ts` - Integrated safety checks, rate limiting, and safety guardrails
---
## 2. Features Implemented
### 2.1 Keyword Detection (AISafetyService)
**Emergency Keywords** (25 keywords)
- not breathing, choking, seizure, unconscious, severe bleeding, etc.
- **Action:** Immediate override - returns emergency response with 911, Poison Control
**Crisis Keywords** (17 keywords)
- suicide, self-harm, postpartum depression, abuse, hopeless, etc.
- **Action:** Immediate override - returns crisis hotlines (988, 1-800-944-4773, 741741)
**Medical Keywords** (27 keywords)
- fever, vomiting, rash, cough, ear infection, medication, etc.
- **Action:** Add medical disclaimer, allow AI response with disclaimer
**Developmental Keywords** (11 keywords)
- delay, autism, ADHD, regression, not talking, not walking, etc.
- **Action:** Add developmental disclaimer with CDC resources
**Stress Keywords** (13 keywords)
- overwhelmed, burnout, exhausted, crying, isolated, etc.
- **Action:** Add stress support resources (Postpartum Support, Parents Anonymous)
### 2.2 Output Safety Moderation
**Unsafe Pattern Detection** (4 regex patterns)
- Dosage patterns: `/\d+\s*(mg|ml|oz|tbsp|tsp)\s*(of|every|per)/i`
- Specific instructions: `/give\s+(him|her|them|baby|child)\s+\d+/i`
- Diagnostic language: `/diagnose|diagnosis|you have|they have/i`
- Definitive statements: `/definitely|certainly\s+(is|has)/i`
**Action:** Prepend medical disclaimer if unsafe patterns detected
### 2.3 Safety Response Templates
**Emergency Response**
- 911 instructions
- CPR guidance if not breathing
- Poison Control: 1-800-222-1222
**Crisis Hotline Response**
- National Suicide Prevention Lifeline: 988
- Postpartum Support International: 1-800-944-4773
- Crisis Text Line: Text "HOME" to 741741
- Childhelp National Child Abuse Hotline: 1-800-422-4453
**Medical Disclaimer**
- Clear warning about not being medical professional
- Red flags requiring immediate care
- When to call pediatrician
**Developmental Disclaimer**
- "Every child develops at their own pace"
- CDC Milestone Tracker link
- Early Intervention Services recommendation
**Stress Support**
- Validation of parental feelings
- Support hotlines
- Self-care reminders
### 2.4 System Prompt Safety Guardrails
**Base Safety Prompt**
- Critical safety rules (never diagnose, never prescribe)
- Emergency protocol (always direct to 911)
- Crisis recognition guidance
- Evidence-based sources (AAP, CDC, WHO)
- Scope definition (ages 0-6, no medical diagnosis)
**Dynamic Safety Overrides**
- Medical Safety Override (for medical queries)
- Crisis Response Override (for crisis queries)
- Injected dynamically based on trigger detection
### 2.5 Rate Limiting & Abuse Prevention (AIRateLimitService)
**Daily Rate Limits**
- Free tier: 10 queries/day
- Premium tier: 200 queries/day (fair use)
**Suspicious Pattern Detection**
- Same query >3 times in 1 hour → Flag as repeated_query
- Emergency keywords >5 times/day → Flag as emergency_spam
- Volume >100 queries/day → Flag as unusual_volume
- Crisis keywords >5 times/day → Logged as high-risk (compassionate handling)
**Temporary Restrictions**
- Duration: 24 hours
- Limit: 1 query/hour
- Applied for: emergency_spam, unusual_volume patterns
- Includes reason and expiration tracking
**Usage Tracking**
- Redis-backed rate limit counters
- Query hashing for deduplication
- Hourly and daily pattern analysis
- Admin methods to clear restrictions
---
## 3. Integration Points
### 3.1 AI Chat Flow
```
1. Check rate limit FIRST → Reject if exceeded
2. Sanitize input (prompt injection detection)
3. Comprehensive safety check → Emergency/crisis override if triggered
4. Build context with enhanced safety prompt
5. Generate AI response
6. Output safety check → Add disclaimer if unsafe patterns
7. Response moderation
8. Inject trigger-specific safety responses
9. Track query for suspicious patterns
10. Increment rate limit counter
```
### 3.2 Safety Metrics Logging
All safety triggers are logged with:
- userId
- trigger type (emergency, crisis, medical, etc.)
- keywords matched
- query (first 100 chars)
- timestamp
**TODO:** Store in database for analytics dashboard (marked in code)
---
## 4. Test Coverage
### 4.1 Unit Tests (31 tests - all passing)
✅ Emergency keyword detection (3 tests)
✅ Crisis keyword detection (3 tests)
✅ Medical keyword detection (3 tests)
✅ Developmental keyword detection (2 tests)
✅ Stress keyword detection (2 tests)
✅ Safe query validation (2 tests)
✅ Output safety pattern detection (3 tests)
✅ Emergency response template (1 test)
✅ Crisis response template (1 test)
✅ Medical disclaimer (2 tests)
✅ Stress support (1 test)
✅ Safety response injection (3 tests)
✅ Base safety prompt (2 tests)
✅ Safety overrides (2 tests)
**Test Results:** 31/31 passing (100% success rate)
**Execution Time:** ~9 seconds
---
## 5. API Endpoints Verified
`/api/v1/ai/provider-status` - Returns provider configuration
`/api/v1/ai/chat` - Main chat endpoint with all safety features
`/` - Backend health check (Hello World!)
**Backend Status:** Running successfully on port 3020
**Frontend Status:** Running successfully on port 3000
**AI Provider:** Azure OpenAI (gpt-5-mini) - Configured ✅
---
## 6. Safety Metrics
### 6.1 Keyword Coverage
- **Total Keywords:** 93 keywords across 5 categories
- **Emergency:** 25 keywords
- **Crisis:** 17 keywords
- **Medical:** 27 keywords
- **Developmental:** 11 keywords
- **Stress:** 13 keywords
### 6.2 Response Templates
- **5 Safety Response Templates** (Emergency, Crisis, Medical, Developmental, Stress)
- **4 Crisis Hotlines** integrated
- **3 Emergency Resources** (911, Poison Control, Nurse Hotline)
- **2 Prompt Safety Overrides** (Medical, Crisis)
---
## 7. Remaining TODOs (Future Enhancements)
### Database Integration
- [ ] Store safety metrics in database for analytics
- [ ] Create safety metrics dashboard
- [ ] Implement incident tracking system
### Notifications
- [ ] Email notification when user is restricted
- [ ] Alert on high-risk crisis keyword patterns
### Enhanced Features
- [ ] Multi-language safety responses (currently English only)
- [ ] A/B testing of safety disclaimer effectiveness
- [ ] User feedback on safety responses
---
## 8. Key Technical Decisions
1. **Immediate Override for Emergencies/Crises**
- No AI response generated for emergency/crisis queries
- Returns safety resources immediately
- Prevents any chance of harmful AI advice in critical situations
2. **Soft Disclaimer for Medical Queries**
- AI response still generated but with prominent disclaimer
- Provides helpful information while maintaining safety boundaries
- Includes "when to seek care" guidance
3. **Compassionate Crisis Handling**
- High repeated crisis keywords flagged but not restricted
- User may genuinely need repeated support
- Logged for potential outreach/support
4. **Redis-backed Rate Limiting**
- Fast, distributed rate limiting
- Automatic expiration (daily counters reset at midnight)
- Scalable across multiple backend instances
5. **Comprehensive Testing First**
- 31 test cases before production deployment
- All safety scenarios covered
- 100% test pass rate required
---
## 9. Deployment Checklist
✅ Strategy document created
✅ Services implemented
✅ Integration complete
✅ Tests written and passing (31/31)
✅ Backend compiling successfully (0 errors)
✅ Servers running (backend port 3020, frontend port 3000)
✅ AI provider configured (Azure OpenAI)
⏳ Database migrations (TODO in code comments)
⏳ User documentation
⏳ Monitoring dashboard
**Status:** Ready for production deployment with noted TODOs
---
## 10. Safety Compliance
### HIPAA-Adjacent Considerations
✅ Never diagnose or prescribe
✅ Always redirect medical concerns to professionals
✅ Clear disclaimers on all medical content
### Child Safety (COPPA Compliance)
✅ Age-appropriate responses (0-6 years)
✅ No collection of sensitive child health data
✅ Parental guidance emphasized
### Mental Health Crisis Management
✅ Immediate crisis hotline resources
✅ 24/7 support numbers provided
✅ Non-judgmental, supportive language
---
## 11. Performance Impact
- **Rate Limiting:** Redis-backed, <1ms overhead
- **Keyword Detection:** Linear search, ~O(n) where n=93, <5ms
- **Output Moderation:** 4 regex patterns, <1ms
- **Overall Chat Latency:** +10-15ms (negligible)
---
## 12. Conclusion
**Comprehensive AI Safety system successfully implemented and tested.**
The Maternal App now provides:
- ✅ Immediate emergency response guidance
- ✅ Crisis hotline integration
- ✅ Medical disclaimers and safety boundaries
- ✅ Developmental guidance with professional referrals
- ✅ Stress support for overwhelmed parents
- ✅ Abuse prevention with rate limiting
- ✅ 100% test coverage for safety features
**All core safety features are functional and protecting users immediately.**
---
**Next Steps:**
1. Deploy to production
2. Monitor safety metrics
3. Implement database storage for analytics
4. Create monitoring dashboard
5. User education materials

View File

@@ -1,517 +0,0 @@
# AI Safety Strategy - Maternal App
**Purpose:** Ensure safe, responsible, and helpful AI interactions for parents seeking childcare guidance.
**Last Updated:** October 2, 2025
---
## 1. Safety Principles
### 1.1 Core Safety Values
1. **Medical Disclaimer First** - Never provide medical diagnoses or emergency advice
2. **Crisis Detection** - Recognize mental health crises and provide resources
3. **Age-Appropriate** - Responses suitable for child ages 0-6 years
4. **Evidence-Based** - Reference pediatric guidelines when possible
5. **Non-Judgmental** - Support all parenting styles without criticism
6. **Privacy-Focused** - Never request or store unnecessary medical information
### 1.2 What AI SHOULD Do
- ✅ Provide general parenting information and tips
- ✅ Suggest routines and organizational strategies
- ✅ Explain developmental milestones
- ✅ Offer emotional support and encouragement
- ✅ Direct to professional resources when appropriate
- ✅ Help track and interpret patterns in child's data
### 1.3 What AI MUST NOT Do
- ❌ Diagnose medical conditions
- ❌ Prescribe medications or dosages
- ❌ Handle medical emergencies
- ❌ Replace professional medical advice
- ❌ Make definitive statements about child development delays
- ❌ Encourage unsafe practices
---
## 2. Medical Disclaimer Triggers
### 2.1 Emergency Keywords (Immediate Disclaimer)
Trigger immediate medical disclaimer and emergency guidance:
**Critical Symptoms:**
- `emergency`, `911`, `ambulance`
- `not breathing`, `can't breathe`, `choking`
- `unconscious`, `unresponsive`, `passed out`
- `seizure`, `convulsion`, `shaking uncontrollably`
- `severe bleeding`, `blood loss`, `won't stop bleeding`
- `severe burn`, `burned`, `scalded`
- `poisoning`, `swallowed`, `ingested`
- `head injury`, `fell`, `hit head`
- `allergic reaction`, `anaphylaxis`, `swelling`
**Response Template:**
```
⚠️ EMERGENCY DISCLAIMER ⚠️
This appears to be a medical emergency. Please:
1. Call emergency services immediately (911 in US)
2. If child is not breathing, start CPR if trained
3. Stay calm and follow dispatcher instructions
I'm an AI assistant and cannot provide emergency medical guidance.
Please seek immediate professional medical help.
Emergency Resources:
- US: 911
- Poison Control: 1-800-222-1222
- Nurse Hotline: [Local number]
```
### 2.2 Medical Concern Keywords (Soft Disclaimer)
Trigger medical disclaimer but allow response with disclaimer:
**Symptoms:**
- `fever`, `temperature`, `hot`, `feverish`
- `vomiting`, `throwing up`, `vomit`
- `diarrhea`, `loose stools`, `watery stool`
- `rash`, `spots`, `bumps`, `hives`
- `cough`, `coughing`, `wheezing`
- `ear infection`, `ear pain`, `ear ache`
- `cold`, `flu`, `sick`, `illness`
- `constipation`, `not pooping`, `hard stool`
- `dehydration`, `not drinking`, `dry`
- `injury`, `hurt`, `pain`, `ache`
- `medication`, `medicine`, `dosage`, `dose`
**Response Pattern:**
```
⚠️ Medical Disclaimer: I'm an AI assistant, not a medical professional.
For medical concerns, always consult your pediatrician or healthcare provider.
[General information response, if appropriate]
When to seek immediate care:
- [Specific red flags for the symptom]
Consider calling your pediatrician if:
- [Warning signs]
```
### 2.3 Developmental Concern Keywords
- `delay`, `behind`, `not talking`, `not walking`
- `autism`, `ADHD`, `disability`, `special needs`
- `regression`, `lost skills`, `stopped doing`
**Response Pattern:**
```
⚠️ Developmental Disclaimer: Every child develops at their own pace.
If you have concerns, consult your pediatrician or early intervention specialist.
[General milestone information]
Resources:
- CDC Milestone Tracker: [link]
- Early Intervention Services: [link]
```
---
## 3. Crisis Hotline Integration
### 3.1 Mental Health Crisis Detection
**Crisis Keywords:**
- `suicide`, `kill myself`, `want to die`, `end it all`
- `hurt myself`, `self-harm`, `cutting`
- `can't cope`, `can't do this`, `giving up`
- `hopeless`, `worthless`, `burden`
- `postpartum depression`, `PPD`, `severe depression`
- `psychosis`, `hallucinations`, `voices`
- `abuse`, `hitting`, `hurting`, `violent`
**Crisis Response Template:**
```
🆘 CRISIS SUPPORT 🆘
It sounds like you're going through an incredibly difficult time.
Your feelings are valid, and help is available.
IMMEDIATE CRISIS RESOURCES:
━━━━━━━━━━━━━━━━━━━━━━━━━
🇺🇸 National Suicide Prevention Lifeline
📞 988 (call or text)
💬 Chat: 988lifeline.org
🤱 Postpartum Support International
📞 1-800-944-4773
💬 Text "HELP" to 800-944-4773
🆘 Crisis Text Line
💬 Text "HOME" to 741741
👶 Childhelp National Child Abuse Hotline
📞 1-800-422-4453
These services are:
✓ Free and confidential
✓ Available 24/7
✓ Staffed by trained counselors
✓ No judgment, only support
You don't have to go through this alone. Please reach out.
```
### 3.2 Parental Stress Detection
**Stress Keywords:**
- `overwhelmed`, `stressed`, `exhausted`, `burned out`
- `crying`, `breaking down`, `can't handle`
- `no support`, `alone`, `isolated`
- `angry at baby`, `resentful`, `regret`
**Support Response:**
```
💙 Parenting is Hard 💙
You're not alone in feeling this way. Many parents experience:
- Exhaustion and burnout
- Overwhelming emotions
- Moments of frustration
This doesn't make you a bad parent. It makes you human.
Support Resources:
🤱 Postpartum Support International: 1-800-944-4773
📞 Parents Anonymous: 1-855-427-2736
💬 Crisis Text Line: Text "PARENT" to 741741
Self-Care Reminders:
✓ Taking breaks is necessary, not selfish
✓ Asking for help is a sign of strength
✓ Your mental health matters too
[Followed by relevant coping strategies if appropriate]
```
---
## 4. Content Moderation & Filtering
### 4.1 Input Moderation
**Filter Out:**
- Inappropriate sexual content
- Violent or abusive language
- Requests for illegal activities
- Spam or commercial solicitation
- Personal information requests (addresses, SSN, etc.)
**Moderation Response:**
```
I'm here to provide parenting support and childcare guidance.
This type of content falls outside my intended use.
If you have questions about childcare for children ages 0-6,
I'm happy to help!
```
### 4.2 Output Moderation
**Before Sending AI Response, Check For:**
- Medical advice (trigger disclaimer if present)
- Potentially harmful suggestions
- Contradictory information
- Inappropriate content
- Dosage recommendations (remove/disclaim)
**Content Safety Checks:**
```typescript
const unsafePatterns = [
/\d+\s*(mg|ml|oz|tbsp|tsp)\s*(of|every|per)/i, // Dosage patterns
/give\s+(him|her|them|baby|child)\s+\d+/i, // Specific instructions with amounts
/diagnose|diagnosis|you have|they have/i, // Diagnostic language
/definitely|certainly\s+(is|has)/i, // Definitive medical statements
];
```
---
## 5. Rate Limiting & Abuse Prevention
### 5.1 Current Rate Limits
- **Free Tier:** 10 AI queries per day
- **Premium Tier:** Unlimited queries (with fair use policy)
### 5.2 Enhanced Rate Limiting
**Suspicious Pattern Detection:**
- Same question repeated >3 times in 1 hour
- Medical emergency keywords repeated >5 times in 1 day
- Queries from multiple IPs for same user (account sharing)
- Unusual query volume (>100/day even for premium)
**Action on Suspicious Activity:**
1. Temporary rate limit (1 query per hour for 24 hours)
2. Flag account for manual review
3. Send email notification to user
4. Log to security monitoring
### 5.3 Fair Use Policy (Premium)
- Maximum 200 queries per day (reasonable for active use)
- Queries should be related to childcare (0-6 years)
- No commercial use or data scraping
- No sharing of account credentials
---
## 6. System Prompt Guardrails
### 6.1 Base System Prompt (Always Included)
```
You are a helpful AI assistant for the Maternal App, designed to support
parents of children aged 0-6 years with childcare organization and guidance.
CRITICAL SAFETY RULES:
1. You are NOT a medical professional. Never diagnose or prescribe.
2. For medical emergencies, ALWAYS direct to call 911 immediately.
3. For medical concerns, ALWAYS recommend consulting a pediatrician.
4. Recognize mental health crises and provide crisis hotline resources.
5. Be supportive and non-judgmental of all parenting approaches.
6. Focus on evidence-based information from reputable sources (AAP, CDC, WHO).
7. Never provide specific medication dosages.
8. If asked about serious developmental delays, refer to professionals.
TONE:
- Warm, empathetic, and encouraging
- Clear and concise
- Non-judgmental and inclusive
- Supportive but honest
SCOPE:
- Childcare for ages 0-6 years
- Routines, tracking, organization
- General parenting tips and strategies
- Emotional support for parents
- Interpretation of tracked activity patterns
OUT OF SCOPE:
- Medical diagnosis or treatment
- Legal advice
- Financial planning
- Relationship counseling (beyond parenting partnership)
- Children outside 0-6 age range
```
### 6.2 Context-Specific Safety Additions
**When Medical Keywords Detected:**
```
MEDICAL SAFETY OVERRIDE:
This query contains medical concerns. Your response MUST:
1. Start with a medical disclaimer
2. Avoid definitive statements
3. Recommend professional consultation
4. Provide general information only
5. Include "when to seek immediate care" guidance
```
**When Crisis Keywords Detected:**
```
CRISIS RESPONSE OVERRIDE:
This query indicates a potential crisis. Your response MUST:
1. Acknowledge their feelings without judgment
2. Provide immediate crisis hotline numbers
3. Encourage reaching out for professional help
4. Be brief and focus on resources
5. Do NOT provide coping strategies that could be misinterpreted
```
---
## 7. Monitoring & Analytics
### 7.1 Safety Metrics to Track
**Daily Monitoring:**
- Number of medical disclaimer triggers
- Number of crisis hotline responses sent
- Number of emergency keyword detections
- Number of queries blocked by content filter
- Average response moderation score
**Weekly Review:**
- Trending medical concerns
- Common crisis keywords
- False positive rate for disclaimers
- User feedback on safety responses
### 7.2 Alert Thresholds
**Immediate Alerts:**
- >10 emergency keywords in 1 hour (potential abuse or real emergency pattern)
- >5 crisis keywords from single user in 24 hours (high-risk user)
- Content filter blocking >50 queries/day (attack or misconfiguration)
**Daily Review Alerts:**
- >100 medical disclaimers triggered in 24 hours
- >20 crisis responses in 24 hours
- Pattern of similar medical queries (potential misinformation spread)
---
## 8. User Education
### 8.1 First-Time User Guidance
**On First AI Query, Show:**
```
👋 Welcome to Your AI Parenting Assistant!
I'm here to help with:
✓ Childcare tips and organization
✓ Understanding your baby's patterns
✓ Answering general parenting questions
✓ Providing encouragement and support
Important to Know:
⚠️ I'm NOT a medical professional
⚠️ Always consult your pediatrician for medical concerns
⚠️ Call 911 for emergencies
For the best experience:
💡 Ask specific questions about routines, tracking, or parenting tips
💡 Share your child's age for age-appropriate guidance
💡 Use your activity tracking data for personalized insights
Let's get started! How can I help you today?
```
### 8.2 In-App Safety Reminders
**Random Safety Tips (1 in 20 responses):**
- "Remember: I'm an AI assistant, not a doctor. Always consult your pediatrician for medical advice."
- "Having a tough day? It's okay to ask for help. Check out our Resources section."
- "Emergency? Call 911 immediately. I cannot provide emergency medical guidance."
---
## 9. Implementation Checklist
### 9.1 Backend Implementation
- [ ] Create `ai-safety.service.ts` with keyword detection
- [ ] Implement medical disclaimer injection
- [ ] Add crisis hotline response generator
- [ ] Enhance content moderation filters
- [ ] Update system prompts with safety guardrails
- [ ] Add safety metrics logging
- [ ] Create safety monitoring dashboard
### 9.2 Frontend Implementation
- [ ] Add safety disclaimer modal on first AI use
- [ ] Display crisis hotlines prominently when triggered
- [ ] Show medical disclaimer badges
- [ ] Add "Report Unsafe Response" button
- [ ] Create AI Safety FAQ page
### 9.3 Testing
- [ ] Unit tests for keyword detection (100+ test cases)
- [ ] Integration tests for crisis response flow
- [ ] Manual testing of all disclaimer triggers
- [ ] User acceptance testing with parents
- [ ] Safety audit by medical professional (recommended)
### 9.4 Documentation
- [ ] User-facing AI Safety policy
- [ ] Developer documentation for safety service
- [ ] Incident response playbook
- [ ] Safety metric reporting template
---
## 10. Incident Response
### 10.1 If Harmful Response is Reported
**Immediate Actions (Within 1 hour):**
1. Flag conversation in database
2. Review full conversation history
3. Identify failure point (keyword detection, content filter, prompt)
4. Temporarily disable AI for affected user if serious
5. Notify safety team
**Follow-up Actions (Within 24 hours):**
1. Root cause analysis
2. Update keyword lists or filters
3. Test fix with similar queries
4. Document incident and resolution
5. Update user with resolution
**Communication:**
- Acknowledge report within 1 hour
- Provide resolution timeline
- Follow up when fixed
- Offer support resources if appropriate
### 10.2 Emergency Escalation
**Escalate to Management If:**
- User reports following harmful AI advice and experiencing negative outcome
- Multiple similar harmful responses in short timeframe
- Media or regulatory inquiry about AI safety
- Suicidal ideation not properly handled by crisis detection
---
## 11. Regular Safety Audits
### 11.1 Monthly Audits
- Review 100 random AI conversations
- Test all crisis and medical keyword triggers
- Analyze false positive/negative rates
- Update keyword lists based on new patterns
- Review user reports and feedback
### 11.2 Quarterly Reviews
- External safety audit (if possible)
- Update crisis hotline numbers (verify still active)
- Review and update safety policies
- Train team on new safety features
- Benchmark against industry standards
---
## 12. Compliance & Legal
### 12.1 Disclaimers (Required)
- [ ] Terms of Service mention AI limitations
- [ ] Privacy Policy covers AI data usage
- [ ] Medical disclaimer in AI interface
- [ ] Crisis resources easily accessible
### 12.2 Recommended Legal Review
- AI response liability
- Medical advice disclaimers sufficiency
- Crisis response appropriateness
- Age-appropriate content standards
---
## Status: READY FOR IMPLEMENTATION
**Priority:** HIGH - User Safety Critical
**Estimated Implementation Time:** 3-5 days
**Testing Time:** 2 days
**Total:** 5-7 days with testing
**Next Steps:**
1. Implement `AISafetyService` with keyword detection
2. Update `AIService` to integrate safety checks
3. Add crisis hotline database/configuration
4. Create frontend safety components
5. Comprehensive testing with real scenarios
6. User documentation
This strategy ensures the Maternal App AI is helpful, supportive, and above all, SAFE for parents seeking guidance.

View File

@@ -1,500 +0,0 @@
# Maternal App - Development Backlog
**Last Updated**: October 3, 2025
**Status**: Active Development
This document tracks remaining tasks, future enhancements, and technical debt items for the Maternal App project.
---
## 🔴 High Priority (Pre-Launch)
### 1. Date/Time Localization Refinement
**Status**: 70% Complete
**Estimated Effort**: 1-2 hours
**Related**: LOCALIZATION_IMPLEMENTATION_PLAN.md Phase 10
**Completed**:
-`useLocalizedDate` hook created and implemented
- ✅ Activity timestamps use `formatDistanceToNow`
**Remaining**:
- [ ] Apply date-fns locale to all remaining date displays
- [ ] Child birth dates formatting with proper locale
- [ ] Analytics date ranges with locale-specific formatting
- [ ] Ensure consistent date formatting across all components
**Files to Update**:
- `app/children/page.tsx` - Birth date display
- `app/insights/page.tsx` - Date range selectors
- `components/features/analytics/InsightsDashboard.tsx` - Chart date labels
- Any remaining hardcoded date formats
---
### 2. Number Formatting Consistency
**Status**: 70% Complete
**Estimated Effort**: 1-2 hours
**Related**: LOCALIZATION_IMPLEMENTATION_PLAN.md Phase 11
**Completed**:
-`useFormatting` hook created with Intl.NumberFormat
**Remaining**:
- [ ] Apply number formatting throughout app
- [ ] Weight/height values with locale-specific formatting
- [ ] Activity counts and statistics with proper number separators
- [ ] Decimal formatting consistency (1,000.50 vs 1.000,50)
**Files to Update**:
- `app/children/page.tsx` - Weight/height display
- `app/insights/page.tsx` - Statistics and counts
- `components/features/analytics/InsightsDashboard.tsx` - Chart values
- All tracking forms with numeric inputs
---
### 3. Comprehensive Testing Suite
**Status**: Not Started
**Estimated Effort**: 2-4 hours
**Related**: LOCALIZATION_IMPLEMENTATION_PLAN.md Phase 14
**Test Coverage Needed**:
- [ ] Translation coverage test (verify no missing keys)
- [ ] Language switching test (all 7 languages)
- [ ] Unit conversion test (ml↔oz, kg↔lb, cm↔in)
- [ ] Date/time formatting test across locales
- [ ] Layout stability test (ensure no UI breaks with long translations)
- [ ] Number formatting test per locale
- [ ] Measurement unit persistence test
- [ ] Language persistence test across sessions
**Test Files to Create**:
- `__tests__/i18n/translation-coverage.test.ts`
- `__tests__/i18n/language-switching.test.ts`
- `__tests__/utils/unit-conversion.test.ts`
- `__tests__/utils/date-formatting.test.ts`
- `__tests__/utils/number-formatting.test.ts`
---
## 🟡 Medium Priority (Post-Launch)
### 4. Dynamic HTML Lang Attribute
**Status**: Not Started
**Estimated Effort**: 30 minutes
**Related**: LOCALIZATION_IMPLEMENTATION_PLAN.md Phase 1.4
**Description**: Update `<html lang="">` attribute dynamically when language changes for better SEO and accessibility.
**Files to Update**:
- `app/layout.tsx` - Add dynamic lang attribute based on i18n state
**Implementation**:
```typescript
// app/layout.tsx
export default function RootLayout({ children }) {
const { i18n } = useTranslation();
useEffect(() => {
document.documentElement.lang = i18n.language;
}, [i18n.language]);
// ...
}
```
---
### 5. Redux State Integration for User Preferences
**Status**: Not Started
**Estimated Effort**: 1-2 hours
**Related**: LOCALIZATION_IMPLEMENTATION_PLAN.md Phase 5.1
**Description**: Currently using localStorage and API calls. Should integrate with Redux for better state management.
**Files to Update**:
- `store/slices/userSlice.ts` - Add language and measurementUnit to state
**Implementation**:
```typescript
interface UserState {
// ... existing fields
language: string;
measurementUnit: 'metric' | 'imperial';
}
```
---
### 6. Component Localization Review
**Status**: Partially Complete
**Estimated Effort**: 2-3 hours
**Related**: LOCALIZATION_IMPLEMENTATION_PLAN.md Phase 9.2
**Components Completed**:
- ✅ AppShell, MobileNav, TabBar
- ✅ LanguageSelector, MeasurementUnitSelector
- ✅ Main pages (dashboard, track, children, family, settings, ai-assistant, insights)
**Components to Review**:
- [ ] `components/common/` - Common dialogs, buttons, alerts
- [ ] `components/features/` - Activity cards, forms
- [ ] `components/children/` - ChildDialog, DeleteConfirmDialog
- [ ] `components/family/` - Family member components
- [ ] Error boundaries and fallback UIs
- [ ] Loading states and skeletons
---
## 🟢 Low Priority (Future Enhancements)
### 7. Professional Translation Review
**Status**: All Translations Complete
**Estimated Effort**: External service, 1-2 weeks
**Related**: LOCALIZATION_IMPLEMENTATION_PLAN.md Phase 13.2
**Description**: All 7 languages have been machine-translated with cultural context. Native speaker review recommended before production launch.
**Languages to Review**:
- [ ] Spanish (es-ES) - Native speaker validation
- [ ] French (fr-FR) - Native speaker validation
- [ ] Portuguese (pt-BR) - Native speaker validation
- [ ] Simplified Chinese (zh-CN) - Native speaker validation
- [ ] German (de-DE) - Native speaker validation
- [ ] Italian (it-IT) - Native speaker validation
**Deliverables**:
- Cultural appropriateness verification
- Grammar and syntax corrections
- Parenting terminology accuracy
- Regional variations (if needed)
---
### 8. Developer Documentation
**Status**: Not Started
**Estimated Effort**: 1-2 hours
**Related**: LOCALIZATION_IMPLEMENTATION_PLAN.md Phase 15
**Documents to Create**:
- [ ] `docs/LOCALIZATION_GUIDE.md` - How to add translations, languages, best practices
- [ ] Update `docs/implementation-gaps.md` - Mark localization as complete
- [ ] `docs/UNIT_CONVERSION_GUIDE.md` - How unit conversions work
**Content Needed**:
```markdown
# LOCALIZATION_GUIDE.md
- How to add new translation keys
- How to add new languages
- Translation file structure
- Best practices (interpolation, pluralization)
- How to test translations
# UNIT_CONVERSION_GUIDE.md
- Storage strategy (always metric)
- Display strategy (user preference)
- How to use UnitInput component
- How to add new unit types
```
---
### 9. Additional Language Support
**Status**: Not Started
**Estimated Effort**: 2-3 hours per language
**Related**: Future enhancement
**Potential Languages**:
- [ ] Arabic (ar-SA) - Requires RTL support
- [ ] Hindi (hi-IN) - Large user base
- [ ] Japanese (ja-JP) - Advanced market
- [ ] Korean (ko-KR) - Advanced market
- [ ] Russian (ru-RU) - Large user base
**Technical Requirements for RTL**:
- RTL layout support in CSS
- Mirror UI components
- Text alignment adjustments
- Icon direction handling
---
### 10. Additional Unit Types
**Status**: Not Started
**Estimated Effort**: 2-3 hours
**Related**: LOCALIZATION_IMPLEMENTATION_PLAN.md - Future Enhancements
**Unit Types to Add**:
- [ ] Temperature (°C / °F) - For fever tracking
- [ ] Time format preference (12h / 24h)
- [ ] Date format preference (MM/DD/YYYY vs DD/MM/YYYY)
- [ ] Regional variations (UK vs US imperial)
**Implementation**:
- Update `lib/utils/unitConversion.ts`
- Update `components/forms/UnitInput.tsx`
- Add to user preferences schema
- Add to onboarding flow
---
### 11. Translation Management System
**Status**: Not Started
**Estimated Effort**: 4-6 hours
**Priority**: Low (Nice to have)
**Description**: Implement a system for managing translations outside of JSON files for easier collaboration with translators.
**Options**:
1. **Local Tool**: Custom admin panel for translation management
2. **Third-Party**: Integration with services like Lokalise, Crowdin, or POEditor
**Benefits**:
- Non-developers can update translations
- Translation memory and consistency
- Automatic missing key detection
- Version control for translations
- Collaboration with professional translators
---
## 🔧 Technical Debt
### 12. Remove Unused MobileNav Component
**Status**: Identified
**Estimated Effort**: 15 minutes
**Priority**: Low
**Description**: `components/layouts/MobileNav/MobileNav.tsx` is no longer used since we unified the header. Consider removing or archiving.
**Files to Update**:
- Delete or archive `components/layouts/MobileNav/MobileNav.tsx`
- Remove imports from AppShell if not already removed
---
### 13. Optimize Translation Bundle Size
**Status**: Not Started
**Estimated Effort**: 2-3 hours
**Priority**: Medium
**Description**: Currently loading all translations. Implement lazy loading per namespace and language.
**Implementation**:
- Configure i18next backend plugin
- Load translations on demand
- Cache loaded translations
- Preload critical namespaces (common, errors)
**Expected Impact**:
- Reduce initial bundle size by ~60-70%
- Faster initial page load
- Better performance on slow connections
---
### 14. Accessibility (a11y) Audit
**Status**: Not Started
**Estimated Effort**: 3-4 hours
**Priority**: High (Pre-Launch)
**Areas to Review**:
- [ ] Keyboard navigation throughout app
- [ ] Screen reader compatibility (ARIA labels)
- [ ] Color contrast ratios (WCAG AA compliance)
- [ ] Focus management in dialogs
- [ ] Form validation messages accessibility
- [ ] Error messages accessibility
- [ ] Language selector accessibility
**Tools to Use**:
- axe DevTools
- WAVE browser extension
- Screen reader testing (NVDA/JAWS)
---
### 15. Performance Optimization
**Status**: Not Started
**Estimated Effort**: 2-4 hours
**Priority**: Medium
**Optimization Opportunities**:
- [ ] Implement code splitting for routes
- [ ] Lazy load heavy components (charts, analytics)
- [ ] Optimize image loading (next/image)
- [ ] Implement virtual scrolling for long lists
- [ ] Reduce re-renders with React.memo
- [ ] Optimize bundle size analysis
**Metrics to Track**:
- First Contentful Paint (FCP) < 1.5s
- Largest Contentful Paint (LCP) < 2.5s
- Time to Interactive (TTI) < 3.5s
- Cumulative Layout Shift (CLS) < 0.1
---
### 16. Push Notification Permission UI
**Status**: Not Started
**Estimated Effort**: 2-3 hours (Frontend) + 3-4 hours (Backend)
**Priority**: Low (Post-Launch)
**Related**: PWA Features (95% complete, this is the remaining 5%)
**Description**: Implement web push notification permission request and backend Firebase FCM integration.
**Frontend Requirements**:
- [ ] Create PushNotificationPermission component
- [ ] Request notification permission from browser
- [ ] Handle permission states (granted, denied, default)
- [ ] Send FCM token to backend when granted
- [ ] Show permission prompt at appropriate time (not immediately)
- [ ] Store permission state in user preferences
**Backend Requirements**:
- [ ] Firebase Cloud Messaging (FCM) integration
- [ ] Store FCM tokens per user/device
- [ ] Create notification sending service
- [ ] Add endpoints: POST /notifications/subscribe, DELETE /notifications/unsubscribe
- [ ] Implement notification templates (activity reminders, family updates)
- [ ] Handle token refresh and cleanup
**Files to Create**:
- Frontend: `components/pwa/PushNotificationPermission.tsx`
- Backend: `src/modules/notifications/fcm.service.ts`
- Backend: `src/modules/notifications/push-notification.service.ts`
**Implementation Notes**:
- Requires Firebase project setup
- Need VAPID keys for web push
- Test on multiple browsers (Chrome, Firefox, Safari)
- iOS requires PWA installed for push notifications
---
## 📋 Future Features
### 17. Offline Mode Enhancements
**Status**: Basic offline support exists
**Estimated Effort**: 6-8 hours
**Priority**: Medium
**Enhancements Needed**:
- [ ] Better offline indicator UI
- [ ] Sync queue visualization
- [ ] Conflict resolution UI
- [ ] Offline data persistence improvements
- [ ] Background sync when connection restored
---
### 18. Voice Input Multi-Language Support
**Status**: Works with backend language detection
**Estimated Effort**: 2-3 hours
**Priority**: Low
**Enhancements Needed**:
- [ ] Language-specific voice models
- [ ] Accent/dialect support
- [ ] Voice command examples per language
- [ ] Improved transcription accuracy
---
### 19. Export/Import Data
**Status**: Not Started
**Estimated Effort**: 4-6 hours
**Priority**: Medium
**Features**:
- [ ] Export activity data (CSV, PDF)
- [ ] Export analytics reports
- [ ] GDPR data export compliance
- [ ] Import data from other baby tracking apps
- [ ] Backup/restore functionality
---
### 20. Dark Mode
**Status**: Not Started
**Estimated Effort**: 3-4 hours
**Priority**: Low
**Implementation**:
- [ ] Add dark mode toggle in settings
- [ ] Create dark theme palette
- [ ] Test all components in dark mode
- [ ] Persist preference
- [ ] System preference detection
---
### 21. Push Notifications Localization
**Status**: Backend supports multi-language
**Estimated Effort**: 2-3 hours
**Priority**: Medium
**Features**:
- [ ] Send notifications in user's preferred language
- [ ] Localized notification templates
- [ ] Time zone awareness
- [ ] Customizable notification preferences
---
## 📊 Progress Tracking
**Total Tasks**: 21
**High Priority**: 3 tasks (15%)
**Medium Priority**: 3 tasks (15%)
**Low Priority**: 15 tasks (71%)
**Estimated Total Effort**: 45-70 hours (1-1.75 weeks)
---
## 🎯 Recommended Implementation Order
### Sprint 1 (Pre-Launch - Critical)
1. Date/Time Localization Refinement (1-2h)
2. Number Formatting Consistency (1-2h)
3. Comprehensive Testing Suite (2-4h)
4. Accessibility Audit (3-4h)
**Total**: 7-12 hours
### Sprint 2 (Post-Launch - Week 1)
5. Dynamic HTML Lang Attribute (30m)
6. Component Localization Review (2-3h)
7. Performance Optimization (2-4h)
8. Developer Documentation (1-2h)
**Total**: 6-10 hours
### Sprint 3 (Post-Launch - Week 2)
9. Redux State Integration (1-2h)
10. Professional Translation Review (External)
11. Optimize Translation Bundle Size (2-3h)
12. Remove Unused Components (15m)
**Total**: 3-5 hours
### Future Sprints
13-20. Feature enhancements and nice-to-haves
---
## 📝 Notes
- This backlog should be reviewed and updated monthly
- Priority levels may change based on user feedback
- Effort estimates are rough and may vary
- Consider user feedback for prioritization
- Some tasks may become obsolete with new requirements
---
**Document Owner**: Development Team
**Review Frequency**: Monthly
**Next Review**: November 3, 2025

View File

@@ -1,109 +0,0 @@
# Features Completed - October 4, 2025
## Photo Upload System Implementation
### ✅ User Profile Photo Upload
**Status**: COMPLETE
**Time**: ~3 hours (planned: 2h)
**What was built**:
- PhotoUpload component with base64 encoding (max 5MB)
- Increased backend body size limit to 10MB
- Added photo_url TEXT column to users table
- Removed PostgreSQL index (exceeded 8KB limit for base64)
- Updated all auth endpoints to return photoUrl
- Added avatar display in header with error handling
- Hidden URL text field for cleaner UX
**Technical challenges solved**:
1. PostgreSQL index size limit (8KB) - removed index completely
2. Express body parser limit (100KB default) - increased to 10MB
3. React import error - added missing useEffect import
4. Next.js caching - required full rebuild
**Files modified**: 15 files across frontend and backend
**Commits**: 6 commits
- `3f31edd` - feat: Add user profile photo upload
- `4527224` - fix: Increase body size limit to 10MB
- `5c69375` - fix: Remove photo_url index
- `31f710d` - feat: Hide photo URL field
- `f083e3e` - fix: Remove TextField completely
- `0519740` - fix: Import useEffect
---
### ✅ Child Photo Upload Enhancement
**Status**: COMPLETE
**Time**: ~1 hour (planned: 1.5h)
**What was built**:
- Reused PhotoUpload component for child profiles
- Updated translations in all 7 languages
- Changed label from "Photo URL (Optional)" to "Child Image (Optional)"
- Photo displays in child cards with avatar fallback
**Files modified**: 8 translation files + ChildDialog.tsx
**Commit**: `afdb51c` - feat: Update child photo label
---
### ✅ Mobile View Grid Layout (2 Cards per Row)
**Status**: COMPLETE
**Time**: ~30 minutes (planned: 1h)
**What was built**:
- Changed children grid from 1 card/row to 2 cards/row on mobile
- Responsive Grid sizing: xs={6} sm={6} md={4}
- Maintained proper touch targets and spacing
**Files modified**: `maternal-web/app/children/page.tsx`
---
### ✅ Collapsible Active Sessions Section
**Status**: COMPLETE
**Time**: ~1 hour
**What was built**:
- Converted SessionsManagement to MUI Accordion
- Converted DeviceTrustManagement to MUI Accordion
- Shows count badge when collapsed
- Smooth expand/collapse animations
**Files modified**:
- `maternal-web/components/settings/SessionsManagement.tsx`
- `maternal-web/components/settings/DeviceTrustManagement.tsx`
---
## Bug Fixes
### ✅ Voice Tracking Data Format
**Fixed**: Voice feeding/sleep commands now save correctly
- Fixed data format mismatch (timestamp/data vs startedAt/metadata)
- Added sleep duration → startTime/endTime conversion
### ✅ Session Persistence After Revocation
**Fixed**: Users are now properly logged out after revoking sessions/devices
### ✅ Voice Modal Status Not Updating
**Fixed**: Voice modal now shows correct status after approve/edit
---
## Summary
**Total features completed today**: 4 high-priority features + 3 bug fixes
**Total time**: ~6 hours
**Total commits**: 10+ commits
**Files modified**: 25+ files
**Next priorities** (from REMAINING_FEATURES.md):
1. Legal Pages & User Menu (3h)
2. EULA Agreement Popup (2h)
3. Cookie Consent Banner (2h)
4. Secondary Color Palette & Accessibility Toggle (4h)
5. AI Response Feedback UI (2h)

View File

@@ -1,286 +0,0 @@
# Embeddings-Based Conversation Memory Implementation
## ✅ Implementation Complete
Successfully implemented vector embeddings-based semantic search for AI conversation memory in the Maternal App.
## 🎯 What Was Implemented
### 1. Database Layer (pgvector)
- ✅ Installed pgvector extension in PostgreSQL 15
- ✅ Created `V014_create_conversation_embeddings.sql` migration
- ✅ Table: `conversation_embeddings` with 1536-dimension vectors
- ✅ HNSW index for fast similarity search (m=16, ef_construction=64)
- ✅ GIN index on topics array for filtering
- ✅ PostgreSQL functions for semantic search:
- `search_similar_conversations()` - General similarity search
- `search_conversations_by_topic()` - Topic-filtered search
### 2. Entity Layer
- ✅ Created `ConversationEmbedding` entity in TypeORM
- ✅ Helper methods for vector conversion:
- `vectorToString()` - Convert array to PostgreSQL vector format
- `stringToVector()` - Parse PostgreSQL vector to array
- `cosineSimilarity()` - Calculate similarity between vectors
### 3. Embeddings Service (`embeddings.service.ts`)
- ✅ Azure OpenAI integration for text-embedding-ada-002
- ✅ Single and batch embedding generation
- ✅ Semantic similarity search with cosine distance
- ✅ Topic-based filtering support
- ✅ User statistics and health check endpoints
- ✅ Backfill capability for existing conversations
**Key Features:**
```typescript
- generateEmbedding(text: string): Promise<EmbeddingGenerationResult>
- generateEmbeddingsBatch(texts: string[]): Promise<EmbeddingGenerationResult[]>
- storeEmbedding(conversationId, userId, messageIndex, role, content, topics)
- searchSimilarConversations(query, userId, options)
- getUserEmbeddingStats(userId)
- healthCheck()
```
### 4. Enhanced Conversation Memory (`conversation-memory.service.ts`)
- ✅ Integrated embeddings service
- ✅ Semantic context retrieval:
- `getSemanticContext()` - Find similar past conversations
- `getConversationWithSemanticMemory()` - Combined traditional + semantic memory
- `storeMessageEmbedding()` - Async embedding storage
- `backfillConversationEmbeddings()` - Migrate existing conversations
**Context Strategy:**
1. Search for semantically similar conversations using current query
2. Combine with traditional message window (20 most recent)
3. Prune to fit 4000 token budget
4. Return enriched context for AI response
### 5. AI Service Integration (`ai.service.ts`)
- ✅ Embedded `EmbeddingsService` in constructor
- ✅ Automatic semantic search on every chat request
- ✅ Async, non-blocking embedding storage for new messages
- ✅ Graceful fallback if embeddings fail
**Integration Flow:**
```typescript
chat(userId, chatDto) {
// 1. Get conversation with semantic memory
const { context } = await conversationMemoryService
.getConversationWithSemanticMemory(conversationId, userMessage);
// 2. Generate AI response using enriched context
const response = await generateWithAzure(context);
// 3. Store embeddings asynchronously (non-blocking)
conversationMemoryService.storeMessageEmbedding(...)
.catch(err => logger.warn(...));
}
```
### 6. AI Module Configuration
- ✅ Added `EmbeddingsService` to providers
- ✅ Added `ConversationEmbedding` to TypeORM entities
- ✅ Full dependency injection
### 7. Testing Endpoints (Public for Testing)
Added test endpoints in `ai.controller.ts`:
```typescript
@Public()
@Post('test/embeddings/generate')
testGenerateEmbedding(body: { text: string })
@Public()
@Post('test/embeddings/search')
testSearchSimilar(body: { query, userId?, threshold?, limit? })
@Public()
@Get('test/embeddings/health')
testEmbeddingsHealth()
@Public()
@Get('test/embeddings/stats/:userId')
testEmbeddingsStats(userId)
```
### 8. Comprehensive Test Suite (`test-embeddings.js`)
Created automated test script with 6 test scenarios:
1. ✅ Health check verification
2. ✅ Embedding generation (1536 dimensions)
3. ✅ Conversation creation with automatic embedding storage
4. ✅ Semantic search validation
5. ✅ User statistics retrieval
6. ✅ Semantic memory integration test
## 🔧 Technical Specifications
### Vector Embeddings
- **Model**: Azure OpenAI `text-embedding-ada-002`
- **Dimensions**: 1536
- **Similarity Metric**: Cosine distance
- **Indexing**: HNSW (Hierarchical Navigable Small World)
- **Default Threshold**: 0.7 (70% similarity)
### Performance Optimizations
- **HNSW Parameters**:
- `m = 16` (max connections per layer)
- `ef_construction = 64` (build quality)
- **Batch Processing**: Up to 100 embeddings per request
- **Async Storage**: Non-blocking embedding persistence
- **Token Budget**: 4000 tokens per context window
- **Cache Strategy**: Recent 20 messages + top 3 semantic matches
### Database Schema
```sql
CREATE TABLE conversation_embeddings (
id VARCHAR(30) PRIMARY KEY,
conversation_id VARCHAR(30) NOT NULL,
user_id VARCHAR(30) NOT NULL,
message_index INTEGER NOT NULL,
message_role VARCHAR(20) NOT NULL,
message_content TEXT NOT NULL,
embedding vector(1536) NOT NULL, -- pgvector type
topics TEXT[], -- Array of topics
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fk_conversation FOREIGN KEY (conversation_id)
REFERENCES ai_conversations(id) ON DELETE CASCADE,
CONSTRAINT fk_user FOREIGN KEY (user_id)
REFERENCES users(id) ON DELETE CASCADE
);
-- HNSW index for fast similarity search
CREATE INDEX idx_conversation_embeddings_vector
ON conversation_embeddings
USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);
-- GIN index for topic filtering
CREATE INDEX idx_conversation_embeddings_topics
ON conversation_embeddings USING GIN (topics);
```
## 📊 Use Cases
### 1. Contextual Parenting Advice
When a parent asks: "My baby is having trouble sleeping"
The system:
1. Generates embedding for the query
2. Searches for similar past conversations (e.g., sleep issues, nap troubles)
3. Retrieves context from semantically related discussions
4. Provides personalized advice based on user's history
### 2. Pattern Recognition
- Identifies recurring concerns across conversations
- Suggests proactive solutions based on similar experiences
- Tracks topic evolution over time
### 3. Cross-Topic Insights
Connects related concerns even if discussed with different wording:
- "sleepless nights" ↔ "insomnia problems"
- "feeding difficulties" ↔ "eating challenges"
- "development delays" ↔ "milestone concerns"
## 🔐 Security & Privacy
- ✅ User-specific search (never cross-user)
- ✅ Cascade deletion with conversation removal
- ✅ No embedding data in API responses (only metadata)
- ✅ Rate limiting on embedding generation
- ✅ Graceful degradation if embeddings fail
## 📁 Files Created/Modified
### New Files:
1. `/src/database/migrations/V014_create_conversation_embeddings.sql`
2. `/src/database/entities/conversation-embedding.entity.ts`
3. `/src/modules/ai/embeddings/embeddings.service.ts`
4. `/test-embeddings.js` (Test suite)
### Modified Files:
1. `/src/modules/ai/ai.module.ts` - Added embeddings service
2. `/src/modules/ai/ai.service.ts` - Integrated semantic search
3. `/src/modules/ai/memory/conversation-memory.service.ts` - Added semantic methods
4. `/src/modules/ai/ai.controller.ts` - Added test endpoints
5. `/src/database/entities/index.ts` - Exported new entity
## 🚀 How to Test
### 1. Health Check
```bash
curl http://localhost:3020/api/v1/ai/test/embeddings/health
```
### 2. Generate Embedding
```bash
curl -X POST http://localhost:3020/api/v1/ai/test/embeddings/generate \
-H "Content-Type: application/json" \
-d '{"text": "My baby is not sleeping well"}'
```
### 3. Search Similar Conversations
```bash
curl -X POST http://localhost:3020/api/v1/ai/test/embeddings/search \
-H "Content-Type: application/json" \
-d '{
"query": "sleep problems",
"userId": "test_user_123",
"threshold": 0.7,
"limit": 5
}'
```
### 4. Run Automated Test Suite
```bash
node test-embeddings.js
```
## 🔄 Migration Path
### For Existing Conversations:
Use the backfill endpoint to generate embeddings for historical data:
```typescript
await conversationMemoryService.backfillConversationEmbeddings(conversationId);
```
This will:
1. Extract all messages from the conversation
2. Generate embeddings in batch
3. Store with detected topics
4. Skip if embeddings already exist
## 📈 Future Enhancements
### Potential Improvements:
1. **Embedding Model Upgrades**: Support for newer models (ada-003, etc.)
2. **Multi-vector Search**: Combine multiple query embeddings
3. **Hybrid Search**: BM25 + vector similarity
4. **Topic Modeling**: Automatic topic extraction with clustering
5. **Reranking**: Post-search relevance scoring
6. **Caching**: Embedding cache for frequent queries
### Performance Tuning:
- IVFFlat index for larger datasets (>1M vectors)
- Quantization for reduced storage
- Approximate search for better speed
## ✅ Verification Checklist
- [x] pgvector extension installed and functional
- [x] Migration V014 applied successfully
- [x] ConversationEmbedding entity created
- [x] EmbeddingsService implemented with Azure OpenAI
- [x] Conversation memory enhanced with semantic search
- [x] AI service integrated with embeddings
- [x] Test endpoints exposed (public for testing)
- [x] Comprehensive test suite created
- [x] Database indexes optimized
- [x] Error handling and fallbacks implemented
- [x] Documentation complete
## 🎉 Status: COMPLETE & READY FOR TESTING
The embeddings-based conversation memory system is fully implemented and integrated into the Maternal App AI service. The system provides semantic search capabilities that enhance the AI's ability to provide contextual, personalized parenting advice based on the user's conversation history.
**Note**: The test endpoints in `ai.controller.ts` are marked as `@Public()` for testing purposes. Remember to remove or properly secure these endpoints before production deployment.

View File

@@ -1,816 +0,0 @@
# Localization Implementation Plan
**Created**: October 3, 2025
**Priority**: HIGH (Pre-Launch)
**Estimated Duration**: 2-3 days
## Overview
Implement comprehensive internationalization (i18n) support for the Maternal App with 5 languages and measurement unit preferences.
## Supported Languages
1. **English (en-US)** - Primary/Default ✅
2. **Spanish (es-ES)** ✅ TRANSLATED
3. **French (fr-FR)** ✅ TRANSLATED
4. **Portuguese (pt-BR)** ✅ TRANSLATED
5. **Simplified Chinese (zh-CN)** ✅ TRANSLATED
6. **German (de-DE)** ✅ TRANSLATED (NEW)
7. **Italian (it-IT)** ✅ TRANSLATED (NEW)
## Current Status - Updated October 3, 2025
### ✅ Already Completed (Backend)
- Backend multilanguage support for AI responses
- AI safety responses in 5 languages
- MultiLanguageService with language detection
### ✅ Completed (Frontend - Phases 1-9)
-**Phase 1**: i18next framework installed and configured
-**Phase 2**: Translation files structure created (40 files: 5 languages × 8 namespaces)
-**Phase 3**: Custom hooks created (useTranslation, useLocale, useFormatting)
-**Phase 4**: Backend user schema updated with measurementUnit in preferences JSONB
-**Phase 5**: Language & measurement selectors in Settings page
-**Phase 7**: Settings page fully localized with preferences
-**Phase 8**: Measurement unit conversion utilities implemented
-**Phase 9**: Applied localization to core pages:
- Login & authentication pages
- Dashboard with welcome message, quick actions, summary
- Navigation (AppShell, MobileNav, TabBar)
- Track main page (activity selection)
- Children page (with age formatting & pluralization)
- All connection status indicators
### ✅ Translation Files Created and Fully Translated (77 files)
- `common.json` - UI strings, navigation, connection ✅ **ALL 7 LANGUAGES**
- `auth.json` - Authentication pages ✅ **ALL 7 LANGUAGES**
- `dashboard.json` - Dashboard/home page ✅ **ALL 7 LANGUAGES**
- `tracking.json` - Activity tracking ✅ **ALL 7 LANGUAGES**
- `children.json` - Child management ✅ **ALL 7 LANGUAGES**
- `settings.json` - Settings page ✅ **ALL 7 LANGUAGES**
- `ai.json` - AI assistant ✅ **ALL 7 LANGUAGES**
- `errors.json` - Error messages ✅ **ALL 7 LANGUAGES**
- `family.json` - Family management ✅ **ALL 7 LANGUAGES**
- `insights.json` - Analytics/insights ✅ **ALL 7 LANGUAGES**
- `onboarding.json` - Onboarding flow ✅ **ALL 7 LANGUAGES**
**Languages**: English (en), Spanish (es), French (fr), Portuguese (pt), Chinese (zh), German (de), Italian (it)
**Total Files**: 77 translation files (11 files × 7 languages)
**Status**: 100% professionally translated with cultural context
### ⏳ Remaining To Be Implemented
- Language selector in onboarding flow (Phase 6)
- Individual tracking pages (feeding, sleep, diaper, medicine) with unit conversions (Phase 12)
- Date/time localization throughout app (Phase 10)
- Number formatting per locale (Phase 11)
- Comprehensive testing (Phase 14)
### 🎉 NEWLY COMPLETED (October 3, 2025)
-**All 7 languages fully translated** (77 translation files)
-**Family management localization** - Complete in all 7 languages
-**Analytics/insights localization** - Complete in all 7 languages
-**Settings page localization** - Complete in all 7 languages
-**Onboarding flow translations** - Complete in all 7 languages
-**German (de) translations** - NEW language added with all 11 files
-**Italian (it) translations** - NEW language added with all 11 files
-**Frontend card symmetry** - All pages updated with consistent card widths
---
## Phase 1: Framework Setup ✅ COMPLETED
### 1.1 Install Dependencies - latest versions only! ✅
**Files**: `package.json`
```bash
npm install i18next react-i18next i18next-browser-languagedetector
npm install date-fns # Already installed, confirm locales
```
**Packages**:
- `i18next` - Core i18n framework
- `react-i18next` - React bindings
- `i18next-browser-languagedetector` - Auto-detect user language
### 1.2 Create i18n Configuration ✅
**File**: `lib/i18n/config.ts` (CREATED)
- ✅ Initialize i18next
- ✅ Configure language detector
- ✅ Set up fallback language (en-US)
- ✅ Configure interpolation
- ✅ Load translation resources
### 1.3 Create i18n Provider ✅
**File**: `components/providers/I18nProvider.tsx` (CREATED)
- ✅ Wrap app with I18nextProvider
- ✅ Initialize i18n on mount
- ✅ Handle language loading states
### 1.4 Update Root Layout ✅
**File**: `app/layout.tsx` (MODIFIED)
- ✅ Add I18nProvider to provider stack
- ⏳ Set html lang attribute dynamically (TODO)
---
## Phase 2: Translation Files Structure ✅ COMPLETED
### 2.1 Directory Structure
```
locales/
├── en/
│ ├── common.json # Common UI strings (buttons, labels, etc.)
│ ├── auth.json # Authentication pages
│ ├── dashboard.json # Dashboard/home page
│ ├── tracking.json # Activity tracking
│ ├── children.json # Child management
│ ├── family.json # Family management
│ ├── ai.json # AI assistant
│ ├── analytics.json # Analytics/insights
│ ├── settings.json # Settings page
│ ├── onboarding.json # Onboarding flow
│ ├── errors.json # Error messages
│ └── validation.json # Form validation messages
├── es/
│ └── [same structure]
├── fr/
│ └── [same structure]
├── pt/
│ └── [same structure]
└── zh/
└── [same structure]
```
### 2.2 Translation Keys Structure
**Example - common.json**:
```json
{
"nav": {
"dashboard": "Dashboard",
"track": "Track",
"children": "Children",
"family": "Family",
"ai": "AI Assistant",
"analytics": "Analytics",
"settings": "Settings"
},
"buttons": {
"save": "Save",
"cancel": "Cancel",
"delete": "Delete",
"edit": "Edit",
"add": "Add",
"submit": "Submit",
"back": "Back",
"next": "Next",
"confirm": "Confirm"
},
"units": {
"metric": "Metric",
"imperial": "Imperial",
"ml": "ml",
"oz": "oz",
"cm": "cm",
"in": "in",
"kg": "kg",
"lb": "lb"
}
}
```
---
## Phase 3: Custom Hooks ✅ COMPLETED
### 3.1 useTranslation Hook ✅
**File**: `hooks/useTranslation.ts` (CREATED)
- ✅ Re-export from react-i18next with type safety
- ✅ Custom hook for easier usage
### 3.2 useLocale Hook ✅
**File**: `hooks/useLocale.ts` (CREATED)
- ✅ Get current locale
- ✅ Change locale
- ✅ Get available locales
- ✅ Get locale display name
- ✅ Measurement system management
### 3.3 useFormatting Hook ✅
**File**: `hooks/useFormatting.ts` (CREATED)
- ✅ Format dates based on locale
- ✅ Format numbers based on locale
- ✅ Format currency based on locale
- ✅ Format units based on preference
---
## Phase 4: Measurement Unit Preference ✅ COMPLETED
### 4.1 Backend Schema Update ✅
**Implementation**: Used existing `preferences` JSONB column from V005_add_user_preferences.sql
- No new migration needed - reused existing preferences column
- Added `measurementUnit` as optional field in preferences object
### 4.2 Update User Entity ✅
**File**: `src/database/entities/user.entity.ts` (MODIFIED)
Added to preferences type:
```typescript
@Column({ type: 'jsonb', nullable: true })
preferences?: {
notifications?: boolean;
emailUpdates?: boolean;
darkMode?: boolean;
measurementUnit?: 'metric' | 'imperial';
};
```
### 4.3 Update User DTOs ✅
**File**: `src/modules/auth/dto/update-profile.dto.ts` (CREATED)
Created with validation:
```typescript
export class UserPreferencesDto {
@IsOptional()
@IsIn(['metric', 'imperial'])
measurementUnit?: 'metric' | 'imperial';
}
```
### 4.4 API Endpoints ✅
**File**: `src/modules/auth/auth.controller.ts` (MODIFIED)
- PATCH `/api/v1/auth/profile` - Updated to use UpdateProfileDto with measurementUnit support
- Properly typed and validated
---
## Phase 5: Frontend User Preferences ✅ PARTIALLY COMPLETED
### 5.1 Redux State ⏳
**File**: `store/slices/userSlice.ts` (TODO)
Add to user state:
```typescript
interface UserState {
// ... existing fields
language: string;
measurementUnit: 'metric' | 'imperial';
}
```
### 5.2 Language Selector Component ✅
**File**: `components/settings/LanguageSelector.tsx` (CREATED)
Features:
- ✅ Dropdown with 5 language options
- ✅ Shows language names in native script
- ✅ Updates user preference on change
- ⏳ Persists to backend (pending backend schema)
- ✅ Updates i18n instance
### 5.3 Measurement Unit Selector Component ✅
**File**: `components/settings/MeasurementUnitSelector.tsx` (CREATED)
Features:
- ✅ Dropdown (Metric/Imperial)
- ✅ Updates user preference on change
- ⏳ Persists to backend (pending backend schema)
- ✅ Shows unit examples
---
## Phase 6: Onboarding Flow Integration ✅ COMPLETED
### 6.1 Update Onboarding Page ✅
**File**: `app/(auth)/onboarding/page.tsx` (COMPLETED)
✅ Implemented 5-step flow:
1. Welcome screen
2. Language selection (Step 1)
3. Measurement unit selection (Step 2)
4. Add child (Step 3)
5. Complete (Step 4)
### 6.2 Onboarding Language Step ✅
**Implementation**: Integrated directly in onboarding page
- ✅ Visual language selector with all 7 languages
- ✅ Shows language names in native script (English, Español, Français, Português, 中文, Deutsch, Italiano)
- ✅ Saves preference to backend via `usersApi.updatePreferences`
- ✅ Updates i18n immediately via `useLocale` hook
- ✅ Beautiful card-based selection UI with radio buttons
### 6.3 Onboarding Measurement Step ✅
**Implementation**: Integrated directly in onboarding page
- ✅ Visual metric/imperial selector
- ✅ Shows examples (kg, cm, °C, ml vs lb, in, °F, oz)
- ✅ Saves preference to backend and localStorage
- ✅ Updates measurement system via `useLocale` hook
- ✅ Card-based selection UI for better UX
### 6.4 API Integration ✅
**File**: `app/(auth)/onboarding/page.tsx` (COMPLETED)
- ✅ Language saved to backend via `usersApi.updatePreferences({ language })`
- ✅ Measurement unit saved via `usersApi.updatePreferences({ measurementUnit })`
- ✅ User profile refreshed after each preference update
- ✅ Error handling with graceful fallback
---
## Phase 7: Settings Page Integration ✅ COMPLETED
### 7.1 Update Settings Page ✅
**File**: `app/settings/page.tsx` (MODIFIED)
Add new sections:
-**Preferences** section
- ✅ Language selector
- ✅ Measurement unit selector
### 7.2 Settings UI Components ✅
**Files**:
-`components/settings/LanguageSelector.tsx` (CREATED)
-`components/settings/MeasurementUnitSelector.tsx` (CREATED)
---
## Phase 8: Unit Conversion Utilities ✅ COMPLETED
### 8.1 Conversion Utility ✅
**File**: `lib/utils/unitConversion.ts` (CREATED)
Functions:
-`convertWeight` / `convertWeightToKg`
-`convertHeight` / `convertHeightToCm`
-`convertTemperature` / `convertTemperatureToCelsius`
-`convertVolume` / `convertVolumeToMl`
-`getUnitSymbol`
-`getConversionFactor`
### 8.2 Format Unit Hook ✅
**File**: `hooks/useFormatting.ts` (CREATED)
- ✅ Get user's measurement preference
- ✅ Format value with correct unit
- ✅ Convert between units
- ✅ Display with locale-specific formatting
---
## Phase 9: Apply Localization Throughout App ✅ PARTIALLY COMPLETED
### 9.1 Update All Pages - Status
**✅ Completed Priority Pages**:
1.**Dashboard** (`app/page.tsx`)
- Welcome message with user name interpolation
- Quick actions (all 6 activity cards)
- Today's summary with child name interpolation
- Next predicted activity with variable interpolation
- All UI labels translated in 5 languages
2.**Authentication** (`app/(auth)/login/page.tsx`)
- Login form labels (email, password)
- Submit button, forgot password link
- Social login buttons (Google, Apple)
- Biometric authentication (Face ID/Touch ID)
- Sign up link and all helper text
3.**Track Main Page** (`app/track/page.tsx`)
- Track Activity title and subtitle
- All 5 activity type labels (Feeding, Sleep, Diaper, Medicine, Activity)
- Translated in all 5 languages
4.**Children** (`app/children/page.tsx`)
- Page title and subtitle
- Add/Edit child buttons
- Empty state messages
- Age calculation with proper pluralization (year/years, month/months)
- All error messages
- Gender labels
**✅ Completed Pages**:
5.**Individual Tracking Pages** (`app/track/feeding/`, etc.)
- ✅ Feeding page - Fully localized with unit conversions (ml ↔ oz)
- ✅ Sleep page - Fully localized with duration formatting
- ✅ Diaper page - Fully localized with type labels
- ✅ Medicine page - Fully localized with dosage units
- ✅ Activity page - Fully localized
- ✅ UnitInput component - Automatic unit conversion implemented
6.**Family** (`app/family/page.tsx`)
- ✅ Family management labels - COMPLETED (all 7 languages)
- ✅ Translation keys integrated
7.**AI Assistant** (`app/ai-assistant/page.tsx`)
- ✅ Chat interface uses AI translations from backend
- ✅ Frontend labels fully localized (all 7 languages)
8.**Analytics** (`app/analytics/page.tsx` & `components/features/analytics/InsightsDashboard.tsx`)
- ✅ Chart labels - COMPLETED (all 7 languages)
- ✅ Insights - COMPLETED (all 7 languages)
9.**Settings** (`app/settings/page.tsx`)
- ✅ Completed in Phase 7 (all 7 languages)
### 9.2 Update Components - Status
**✅ Completed Components**:
-`components/layouts/AppShell/AppShell.tsx` - Connection status, presence indicators
-`components/layouts/MobileNav/MobileNav.tsx` - Navigation menu items, logout
-`components/layouts/TabBar/TabBar.tsx` - Bottom navigation tabs
-`components/settings/LanguageSelector.tsx` - Language preference UI
-`components/settings/MeasurementUnitSelector.tsx` - Measurement preference UI
**❌ Remaining Components**:
-`components/common/` - Common dialogs, buttons (may need review)
-`components/features/` - Activity cards, forms (need review)
-`components/children/` - Child dialogs (ChildDialog, DeleteConfirmDialog)
-`components/family/` - Family components
---
## Phase 10: Date/Time Localization
### 10.1 Date Formatting Utility
**File**: `lib/i18n/date-formats.ts` (NEW)
Using date-fns with locales:
```typescript
import { format } from 'date-fns';
import { enUS, es, fr, ptBR, zhCN } from 'date-fns/locale';
const locales = { en: enUS, es, fr, pt: ptBR, zh: zhCN };
export function formatDate(date: Date, formatStr: string, locale: string) {
return format(date, formatStr, { locale: locales[locale] });
}
```
### 10.2 Update Date Displays
Apply locale-aware date formatting:
- Activity timestamps
- Child birth dates
- Analytics date ranges
---
## Phase 11: Number Localization
### 11.1 Number Formatting Utility
**File**: `lib/i18n/number-formats.ts` (NEW)
Using Intl.NumberFormat:
```typescript
export function formatNumber(value: number, locale: string) {
return new Intl.NumberFormat(locale).format(value);
}
export function formatDecimal(value: number, locale: string, decimals = 1) {
return new Intl.NumberFormat(locale, {
minimumFractionDigits: decimals,
maximumFractionDigits: decimals,
}).format(value);
}
```
### 11.2 Apply Number Formatting
- Activity amounts (ml/oz)
- Sleep duration (hours)
- Weight/height measurements
---
## Phase 12: Tracking Forms with Unit Preferences ✅ COMPLETED
### 12.1 Update Feeding Form ✅
**File**: `app/track/feeding/page.tsx` (COMPLETED)
- ✅ Shows ml or oz input based on user preference
- ✅ Converts to metric for API storage
- ✅ Displays in user's preferred unit
- ✅ Fully localized with all form labels
### 12.2 Update Child Profile Form ✅
**File**: `app/children/page.tsx` (COMPLETED)
- ✅ Weight input (kg/lb) with unit conversion
- ✅ Height input (cm/in) with unit conversion
- ✅ Converts to metric for API storage
### 12.3 Universal Input Component ✅
**File**: `components/forms/UnitInput.tsx` (CREATED & IMPLEMENTED)
✅ Implemented Props:
- `type: 'volume' | 'weight' | 'height'`
- `value: number`
- `onChange: (value: number) => void`
- ✅ Auto-converts based on user preference
- ✅ Integrated with all tracking forms
---
## Phase 13: Translation Files Content
### 13.1 English Translations (Base)
**Estimate**: ~500-800 translation keys across all files
Create complete English translations for:
- All UI strings
- All form labels/placeholders
- All error messages
- All validation messages
### 13.2 Professional Translation ✅ COMPLETED
**Status**: ✅ All languages professionally translated with cultural context
**Completed Translations**:
- ✅ Spanish (es-ES) - All 11 files
- ✅ French (fr-FR) - All 11 files
- ✅ Portuguese (pt-BR) - All 11 files
- ✅ Simplified Chinese (zh-CN) - All 11 files
- ✅ German (de-DE) - All 11 files (NEW)
- ✅ Italian (it-IT) - All 11 files (NEW)
**Translation Quality**:
- Natural, culturally appropriate expressions
- Proper grammar and syntax for each language
- Context-aware parenting and childcare terminology
- Consistent terminology throughout all files
**Recommendation**: Native speaker review recommended for production deployment
---
## Phase 14: Testing
### 14.1 Translation Coverage Test
- Verify all strings are externalized
- No hardcoded English strings remain
- All translation keys exist in all languages
### 14.2 Language Switching Test
- Switch between all 5 languages
- Verify UI updates correctly
- Verify no layout breaks
### 14.3 Unit Conversion Test
- Test all conversions (ml↔oz, kg↔lb, cm↔in)
- Verify correct rounding
- Verify storage in consistent units (metric)
### 14.4 Date/Time Test
- Verify dates display correctly per locale
- Test all date formats (short, long, relative)
### 14.5 RTL Support (Future)
**Note**: Chinese doesn't require RTL, but document for future Arabic support
---
## Phase 15: Documentation
### 15.1 Update Implementation Gaps
**File**: `docs/implementation-gaps.md` (MODIFY)
Mark localization as ✅ COMPLETED
### 15.2 Developer Guide
**File**: `docs/LOCALIZATION_GUIDE.md` (NEW)
Document:
- How to add new translation keys
- How to add new languages
- Translation file structure
- Best practices
### 15.3 Update User Documentation
Document language and measurement preferences in user guide
---
## Implementation Order
### Day 1: Framework & Structure
1. ✅ Install dependencies
2. ✅ Create i18n configuration
3. ✅ Create i18n provider
4. ✅ Create hooks (useTranslation, useLocale, useFormatting)
5. ✅ Set up translation file structure
6. ✅ Create English base translations (common, auth, dashboard)
### Day 2: Preferences & Components
7. ✅ Backend schema update for measurementUnit
8. ✅ Update User entity and DTOs
9. ✅ Create LanguageSelector component
10. ✅ Create MeasurementUnitSelector component
11. ✅ Update onboarding flow
12. ✅ Update settings page
13. ✅ Create unit conversion utilities
### Day 3: Apply Throughout App
14. ✅ Update all pages with translations
15. ✅ Apply unit conversions to tracking forms
16. ✅ Apply date/time localization
17. ✅ Complete all English translations
18. ✅ Test language switching
19. ✅ Test unit conversions
### Post-Implementation (Optional)
20. Professional translation for other 4 languages
21. Native speaker review
22. Documentation updates
---
## Key Files Checklist
### New Files (27 total)
- [ ] `lib/i18n/config.ts`
- [ ] `components/providers/I18nProvider.tsx`
- [ ] `hooks/useLocale.ts`
- [ ] `hooks/useFormatting.ts`
- [ ] `hooks/useUnitFormat.ts`
- [ ] `lib/units/conversions.ts`
- [ ] `lib/i18n/date-formats.ts`
- [ ] `lib/i18n/number-formats.ts`
- [ ] `components/settings/LanguageSelector.tsx`
- [ ] `components/settings/MeasurementUnitSelector.tsx`
- [ ] `components/settings/LanguageSettings.tsx`
- [ ] `components/settings/MeasurementSettings.tsx`
- [ ] `components/onboarding/LanguageStep.tsx`
- [ ] `components/onboarding/MeasurementStep.tsx`
- [ ] `components/forms/UnitInput.tsx`
- [ ] `locales/en/*.json` (11 files)
- [ ] `locales/es/*.json` (11 files - future)
- [ ] `locales/fr/*.json` (11 files - future)
- [ ] `locales/pt/*.json` (11 files - future)
- [ ] `locales/zh/*.json` (11 files - future)
- [ ] `src/database/migrations/V0XX_add_measurement_preference.sql`
- [ ] `docs/LOCALIZATION_GUIDE.md`
### Modified Files (15 total)
- [ ] `package.json`
- [ ] `app/layout.tsx`
- [ ] `store/slices/userSlice.ts`
- [ ] `src/database/entities/user.entity.ts`
- [ ] `src/modules/auth/dto/register.dto.ts`
- [ ] `src/modules/auth/dto/update-profile.dto.ts`
- [ ] `app/(auth)/onboarding/page.tsx`
- [ ] `app/settings/page.tsx`
- [ ] `app/page.tsx` (dashboard)
- [ ] `app/track/feeding/page.tsx`
- [ ] `app/track/sleep/page.tsx`
- [ ] `app/track/diaper/page.tsx`
- [ ] `app/children/page.tsx`
- [ ] `app/family/page.tsx`
- [ ] `docs/implementation-gaps.md`
---
## Success Criteria
### ✅ Functionality
- [ ] All 5 languages selectable and functional
- [ ] Language preference persists across sessions
- [ ] Measurement unit preference persists across sessions
- [ ] All UI strings externalized (no hardcoded English)
- [ ] Unit conversions work correctly (ml↔oz, kg↔lb, cm↔in)
- [ ] Dates display correctly per locale
- [ ] Numbers format correctly per locale
### ✅ User Experience
- [ ] Language can be selected in onboarding
- [ ] Language can be changed in settings
- [ ] Measurement unit can be selected in onboarding
- [ ] Measurement unit can be changed in settings
- [ ] UI updates immediately when language changes
- [ ] No layout breaks when changing languages
- [ ] Form inputs show correct units based on preference
### ✅ Technical
- [ ] All translation keys defined
- [ ] No missing translation warnings
- [ ] Type-safe translation usage (TypeScript)
- [ ] Backend stores preferences correctly
- [ ] Redux state syncs with backend
---
## Notes
### Translation Best Practices
1. Use namespaces to organize translations
2. Use interpolation for dynamic values: `t('welcome', { name })`
3. Use pluralization: `t('items', { count })`
4. Keep keys descriptive: `auth.login.emailLabel` not `auth.e1`
5. Avoid concatenation, use complete sentences
### Unit Conversion Strategy
- **Storage**: Always store in metric (ml, kg, cm) in database
- **Display**: Convert to user's preferred unit for display
- **Input**: Accept user's preferred unit, convert to metric before API call
- **Consistency**: Ensure all measurements use the same preference
### Performance Considerations
- Lazy load translation files per namespace
- Cache translations in browser
- Preload critical translations (common, errors)
### Future Enhancements
- Add more languages (Arabic, German, Hindi, etc.)
- Add more units (temperature: °C/°F)
- Add regional date formats (MM/DD vs DD/MM)
- Add time format preferences (12h vs 24h)
---
## Remaining Tasks Summary - UPDATED
### 🟡 Medium Priority (User Experience Enhancement)
1. **Date/Time Localization** (Phase 10) - Partially Done
-`useLocalizedDate` hook created and implemented
- ✅ Activity timestamps use `formatDistanceToNow`
- ⏳ Apply date-fns locale to remaining date displays
- ⏳ Child birth dates formatting
- ⏳ Analytics date ranges with locale
- **Estimated Effort**: 1-2 hours (mostly done)
2. **Number Formatting** (Phase 11) - Partially Done
-`useFormatting` hook created with Intl.NumberFormat
- ⏳ Apply number formatting throughout app
- ⏳ Weight/height values with locale formatting
- ⏳ Activity counts and statistics
- **Estimated Effort**: 1-2 hours (mostly done)
### 🟢 Low Priority (Nice to Have)
3.**Onboarding Flow** (Phase 6) - COMPLETED
- ✅ Onboarding translations complete (all 7 languages)
- ✅ Language selection step UI implemented
- ✅ Measurement unit selection step UI implemented
- ✅ Preferences saved to backend during onboarding
- ✅ 5-step onboarding flow: Welcome → Language → Measurements → Add Child → Complete
- **Status**: FULLY IMPLEMENTED
### 🟢 Low Priority (Future Enhancements)
4. **Professional Translation Review** (Optional)
- ✅ All 6 non-English languages translated with cultural context
- ⏳ Native speaker validation recommended for production
- ⏳ Cultural appropriateness final check
- **Estimated Effort**: External service, 1-2 weeks
5. **Comprehensive Testing** (Phase 14)
- ⏳ Translation coverage test (verify no missing keys)
- ⏳ Language switching test (all 7 languages)
- ⏳ Unit conversion test (ml↔oz, kg↔lb, cm↔in)
- ⏳ Date/time formatting test
- ⏳ Layout stability test across languages
- **Estimated Effort**: 2-4 hours
6. **Documentation** (Phase 15)
- Create LOCALIZATION_GUIDE.md
- Update implementation-gaps.md
- Developer best practices
- **Estimated Effort**: 1-2 hours
### 📊 Progress Tracking - UPDATED October 3, 2025
**Completed**: 14 phases (1-9, 12, 13.2, and partial 10-11)
**In Progress**: 0 phases
**Remaining**: 2 major phases (10, 11, 14)
**Overall Completion**: ~95% (core functionality + all translations + unit conversions + onboarding)
**🎉 Major Milestones Achieved**:
- ✅ All 77 translation files completed across 7 languages
- ✅ All main pages fully localized and integrated
- ✅ All tracking pages with unit conversions COMPLETED
- ✅ UnitInput component fully implemented and integrated
-**Onboarding flow with language & measurement selection COMPLETED**
- ✅ Frontend card symmetry completed for professional appearance
- ✅ i18n configuration fixed and all languages loading correctly
**Estimated Time to Full Completion**:
- Medium Priority (Phase 10-11 - Date/Number formatting refinement): 2-4 hours
- Low Priority (Phase 14 - Testing, Phase 15 - Documentation): 3-5 hours
- **Total Remaining**: 5-9 hours (0.5-1 day)
---
**Total Project Effort**: 4 days (completed) + 0.5-1 day (remaining) = 4.5-5 days
**Complexity**: Medium
**Priority**: HIGH (Pre-Launch)
**Current Status**: Core functionality 95% complete, translations 100% complete, unit conversions 100% complete, onboarding 100% complete, **PRODUCTION-READY**

View File

@@ -1,177 +0,0 @@
# Package Upgrade Plan
## Overview
Upgrading all packages to latest versions before codebase becomes too complex. Strategy: upgrade incrementally, test after each major upgrade, fix breaking changes.
## Backend Packages to Upgrade
### Critical Major Version Upgrades (Breaking Changes Expected)
1. **NestJS Framework** (v10 → v11) - MAJOR
- @nestjs/common: 10.4.20 → 11.1.6
- @nestjs/core: 10.4.20 → 11.1.6
- @nestjs/platform-express: 10.4.20 → 11.1.6
- @nestjs/platform-socket.io: 10.4.20 → 11.1.6
- @nestjs/websockets: 10.4.20 → 11.1.6
- @nestjs/testing: 10.4.20 → 11.1.6
- @nestjs/cli: 10.4.9 → 11.0.10
- @nestjs/schematics: 10.2.3 → 11.0.7
- **Breaking Changes**: Check NestJS v11 migration guide
- **Risk**: HIGH - Core framework upgrade
- **Test Requirements**: Full regression testing
2. **Apollo Server** (v4 → v5) - MAJOR
- @apollo/server: 4.12.2 → 5.0.0
- **Breaking Changes**: GraphQL schema changes, middleware changes
- **Risk**: MEDIUM - Only affects GraphQL endpoints
- **Test Requirements**: GraphQL endpoint testing
3. **Jest** (v29 → v30) - MAJOR
- jest: 29.7.0 → 30.2.0
- @types/jest: 29.5.14 → 30.0.0
- **Breaking Changes**: Test framework syntax changes
- **Risk**: LOW - Mainly test code
- **Test Requirements**: Run test suite
4. **ESLint** (v8 → v9) - MAJOR
- eslint: 8.57.1 → 9.36.0
- eslint-config-prettier: 9.1.2 → 10.1.8
- **Breaking Changes**: Flat config format
- **Risk**: LOW - Development tool only
- **Test Requirements**: Linting passes
5. **OpenAI SDK** (v5 → v6) - MAJOR
- openai: 5.23.2 → 6.0.1
- **Breaking Changes**: API method signatures
- **Risk**: MEDIUM - Affects AI features
- **Test Requirements**: AI conversation testing
### Minor/Patch Version Upgrades (Low Risk)
6. **AWS SDK** - PATCH
- @aws-sdk/client-s3: 3.899.0 → 3.901.0
- @aws-sdk/lib-storage: 3.900.0 → 3.901.0
- @aws-sdk/s3-request-presigner: 3.899.0 → 3.901.0
- **Risk**: VERY LOW - Patch updates
7. **TypeScript** - PATCH
- typescript: 5.9.2 → 5.9.3
- **Risk**: VERY LOW - Patch update
8. **Node Types** - MAJOR (but safe)
- @types/node: 20.19.18 → 24.6.2
- **Risk**: LOW - Type definitions only
9. **Other Minor Updates**
- @nestjs/graphql: 13.1.0 → 13.2.0
- cache-manager: 7.2.2 → 7.2.3
- redis: 5.8.2 → 5.8.3
## Upgrade Strategy
### Phase 1: Low-Risk Patches (Start Here)
```bash
# Patch updates - safe, no breaking changes
npm update typescript
npm update @aws-sdk/client-s3 @aws-sdk/lib-storage @aws-sdk/s3-request-presigner
npm update cache-manager redis
npm update @types/node
```
- **Test**: Basic compile + server starts
- **Time**: 10 minutes
### Phase 2: Minor Version Bumps
```bash
npm install @nestjs/graphql@latest
```
- **Test**: GraphQL endpoints still work
- **Time**: 15 minutes
### Phase 3: OpenAI SDK Upgrade (Medium Risk)
```bash
npm install openai@latest
```
- **Check**: OpenAI v6 migration guide
- **Fix**: AI conversation code
- **Test**: Voice transcription + AI chat
- **Time**: 30-60 minutes
### Phase 4: Jest Upgrade (Medium Risk)
```bash
npm install -D jest@latest @types/jest@latest
npm install -D ts-jest@latest # May need update too
```
- **Check**: Jest v30 migration guide
- **Fix**: Test configuration
- **Test**: Run full test suite
- **Time**: 30-45 minutes
### Phase 5: ESLint Upgrade (Medium Risk)
```bash
npm install -D eslint@latest eslint-config-prettier@latest
```
- **Check**: ESLint v9 flat config migration
- **Fix**: .eslintrc.js → eslint.config.js
- **Test**: Linting passes
- **Time**: 30-45 minutes
### Phase 6: Apollo Server Upgrade (High Risk)
```bash
npm install @apollo/server@latest
```
- **Check**: Apollo Server v5 migration guide
- **Fix**: GraphQL server setup
- **Test**: All GraphQL queries/mutations
- **Time**: 1-2 hours
### Phase 7: NestJS v11 Upgrade (HIGHEST RISK - DO LAST)
```bash
npm install @nestjs/common@latest @nestjs/core@latest @nestjs/platform-express@latest @nestjs/platform-socket.io@latest @nestjs/websockets@latest
npm install -D @nestjs/cli@latest @nestjs/schematics@latest @nestjs/testing@latest
```
- **Check**: NestJS v11 migration guide: https://docs.nestjs.com/migration-guide
- **Fix**: Breaking changes across entire codebase
- **Test**: FULL regression testing
- **Time**: 2-4 hours
## Testing Checklist After Each Phase
- [ ] Backend compiles with no TypeScript errors
- [ ] Server starts successfully
- [ ] Health endpoint responds
- [ ] Auth endpoints work (login/register)
- [ ] Protected endpoints require JWT
- [ ] Database connections work
- [ ] GraphQL playground loads (if applicable)
- [ ] WebSocket connections work
- [ ] All tests pass
- [ ] No new console warnings
## Rollback Plan
Each phase should be committed separately:
```bash
git add .
git commit -m "Phase X: Upgrade [package names]"
```
If issues arise:
```bash
git revert HEAD
npm install
```
## Estimated Total Time
- Phase 1-2: 30 minutes
- Phase 3-5: 2-3 hours
- Phase 6-7: 3-6 hours
**Total: 5-9 hours** (spread over multiple sessions)
## Notes
- Keep backend server running in watch mode to catch compile errors immediately
- Test each endpoint manually after major upgrades
- Check deprecation warnings in console
- Update this document with any issues encountered

View File

@@ -1,362 +0,0 @@
# Sprint 2 Assessment - Testing & Voice Processing
**Date**: October 3, 2025
**Status**: Pre-Sprint Analysis
**Sprint Goal**: Quality Assurance & Voice Features
---
## 📊 Current State Analysis
### Testing Infrastructure ✅ 80% Complete
#### Backend Tests (Excellent Coverage)
**Unit Tests**: ✅ **COMPLETE**
- 27 test files implemented
- 80%+ code coverage achieved
- 23/26 services tested (~751 test cases)
- Test breakdown:
* Phase 1 (5 auth services): 81 tests
* Phase 2 (5 core services): 135 tests
* Phase 3 (3 analytics services): 75 tests
* Phase 4 (4 AI services): 110 tests
* Phase 5 (2 common services): 95 tests
**E2E/Integration Tests**: 🟡 **PARTIALLY COMPLETE**
- ✅ 4 E2E test files exist:
* `test/app.e2e-spec.ts` (basic health check)
* `test/auth.e2e-spec.ts` (authentication flows - 15,978 bytes)
* `test/children.e2e-spec.ts` (children management - 9,886 bytes)
* `test/tracking.e2e-spec.ts` (activity tracking - 10,996 bytes)
**Missing E2E Tests** (6 modules):
1. ❌ AI module (conversations, embeddings, safety)
2. ❌ Analytics module (patterns, predictions, reports)
3. ❌ Voice module (transcription, intent extraction)
4. ❌ Families module (invitations, permissions)
5. ❌ Photos module (upload, gallery, optimization)
6. ❌ Notifications module (push, email, templates)
**Estimated Effort**: 6-10 hours (1-2 hours per module)
#### Frontend Tests
**E2E Tests**: ❌ **NOT IMPLEMENTED**
- No e2e directory found in maternal-web
- Playwright configured in package.json but no tests written
- Critical user journeys not covered
**Missing Critical Flows**:
1. User registration & onboarding
2. Child management (add/edit/delete)
3. Activity tracking (all types)
4. AI assistant conversation
5. Family invitations
6. Settings & preferences
7. Offline mode & sync
**Estimated Effort**: 8-12 hours
---
### Voice Processing ✅ 90% Complete
#### OpenAI Whisper Integration ✅ **IMPLEMENTED**
**Current Implementation**:
- ✅ Azure OpenAI Whisper fully configured
-`transcribeAudio()` method implemented
- ✅ Multi-language support (5 languages: en, es, fr, pt, zh)
- ✅ Temporary file handling for Whisper API
- ✅ Buffer to file conversion
- ✅ Language auto-detection
**Configuration** (from voice.service.ts):
```typescript
// Azure OpenAI Whisper
- Endpoint: AZURE_OPENAI_WHISPER_ENDPOINT
- API Key: AZURE_OPENAI_WHISPER_API_KEY
- Deployment: AZURE_OPENAI_WHISPER_DEPLOYMENT
- API Version: AZURE_OPENAI_WHISPER_API_VERSION
```
**Features Working**:
- Audio buffer to Whisper transcription ✅
- Language parameter support ✅
- Transcription result with text & language ✅
- Integration with activity extraction ✅
#### Confidence Scoring ✅ **IMPLEMENTED**
- Activity extraction returns confidence (0.0-1.0)
- Confidence based on clarity of description
- Used in feedback system
- Logged for monitoring
**What's Missing**: ❌
- No confidence **threshold enforcement** (accept/reject based on score)
- No **retry logic** for low confidence transcriptions
- No **user confirmation prompt** for low confidence activities
#### Voice Error Recovery 🟡 **PARTIALLY IMPLEMENTED**
**Current Error Handling**:
- ✅ Try-catch blocks in transcribeAudio
- ✅ Throws BadRequestException for missing config
- ✅ Temp file cleanup in finally blocks
- ✅ Error logging to console
**Missing Features**:
1.**Retry Logic**: No automatic retry for failed transcriptions
2.**Fallback Strategies**: No device native speech recognition fallback
3.**Confidence Thresholds**: No rejection of low-confidence results
4.**User Clarification**: No prompts for ambiguous commands
5.**Common Mishear Corrections**: No pattern-based error fixing
6.**Partial Success Handling**: All-or-nothing approach
**Estimated Effort**: 4-6 hours
---
## 🎯 Sprint 2 Recommendations
### Option A: Focus on Testing (Quality First)
**Priority**: Complete testing infrastructure
**Effort**: 14-22 hours
**Impact**: Production readiness, bug prevention, confidence
**Tasks**:
1. Backend E2E tests for 6 modules (6-10h)
2. Frontend E2E tests for 7 critical flows (8-12h)
**Benefits**:
- Catch bugs before production
- Prevent regressions
- Automated quality assurance
- Documentation via tests
### Option B: Focus on Voice (Feature Enhancement)
**Priority**: Complete voice error recovery
**Effort**: 4-6 hours
**Impact**: Better UX, fewer failed voice commands
**Tasks**:
1. Implement retry logic with exponential backoff (1-2h)
2. Add confidence threshold enforcement (1h)
3. Create user clarification prompts (1-2h)
4. Add common mishear corrections (1-2h)
**Benefits**:
- More reliable voice commands
- Better error messages
- Graceful degradation
- User feedback for improvements
### Option C: Hybrid Approach (Recommended)
**Priority**: Critical testing + Voice enhancements
**Effort**: 10-14 hours
**Impact**: Best of both worlds
**Tasks**:
1. Backend E2E tests (top 3 modules: AI, Voice, Analytics) (4-6h)
2. Frontend E2E tests (top 3 flows: auth, tracking, AI) (4-6h)
3. Voice error recovery (confidence + retry) (2-3h)
**Benefits**:
- Covers most critical paths
- Improves voice reliability
- Manageable scope
- Quick wins
---
## 📋 Sprint 2 Task Breakdown
### High Priority (Do First)
#### 1. Backend E2E Tests (6 hours)
- [ ] AI module E2E tests (2h)
* Conversation creation/retrieval
* Message streaming
* Safety features (disclaimers, hotlines)
* Embeddings search
- [ ] Voice module E2E tests (1.5h)
* Audio transcription
* Activity extraction
* Confidence scoring
- [ ] Analytics module E2E tests (1.5h)
* Pattern detection
* Report generation
* Statistics calculation
- [ ] Families module E2E tests (1h)
* Invitations
* Permissions
* Member management
#### 2. Frontend E2E Tests (6 hours)
- [ ] Authentication flow (1h)
* Registration
* Login
* MFA setup
* Biometric auth
- [ ] Activity tracking (2h)
* Add feeding
* Add sleep
* Add diaper
* Edit/delete activities
- [ ] AI Assistant (2h)
* Start conversation
* Send message
* Receive response
* Safety triggers
- [ ] Offline mode (1h)
* Create activity offline
* Sync when online
#### 3. Voice Error Recovery (3 hours)
- [ ] Implement retry logic (1h)
* Exponential backoff
* Max 3 retries
* Different error types
- [ ] Confidence threshold enforcement (1h)
* Reject < 0.6 confidence
* Prompt user for confirmation
* Log low-confidence attempts
- [ ] User clarification prompts (1h)
* "Did you mean...?"
* Alternative interpretations
* Manual correction UI
### Medium Priority (If Time Permits)
#### 4. Additional E2E Tests (4-6 hours)
- [ ] Photos module E2E (1h)
- [ ] Notifications module E2E (1h)
- [ ] Settings & preferences E2E (1h)
- [ ] Family sync E2E (1h)
#### 5. Advanced Voice Features (2-3 hours)
- [ ] Common mishear corrections (1h)
- [ ] Partial transcription handling (1h)
- [ ] Multi-language error messages (1h)
---
## 🔧 Implementation Details
### E2E Test Template (Backend)
```typescript
// test/ai.e2e-spec.ts
describe('AI Module (e2e)', () => {
let app: INestApplication;
let authToken: string;
beforeAll(async () => {
// Setup test app
// Get auth token
});
describe('/ai/conversations (POST)', () => {
it('should create new conversation', async () => {
// Test conversation creation
});
it('should enforce safety features', async () => {
// Test medical disclaimer triggers
});
});
afterAll(async () => {
await app.close();
});
});
```
### E2E Test Template (Frontend - Playwright)
```typescript
// e2e/auth.spec.ts
import { test, expect } from '@playwright/test';
test.describe('Authentication', () => {
test('should register new user', async ({ page }) => {
await page.goto('/register');
await page.fill('[name="email"]', 'test@example.com');
await page.fill('[name="password"]', 'Password123!');
await page.click('button[type="submit"]');
await expect(page).toHaveURL('/onboarding');
});
test('should login with existing user', async ({ page }) => {
// Test login flow
});
});
```
### Voice Retry Logic
```typescript
async transcribeWithRetry(
audioBuffer: Buffer,
language?: string,
maxRetries = 3
): Promise<TranscriptionResult> {
let lastError: Error;
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const result = await this.transcribeAudio(audioBuffer, language);
// Check confidence threshold
if (result.confidence && result.confidence < 0.6) {
throw new Error('Low confidence transcription');
}
return result;
} catch (error) {
lastError = error;
if (attempt < maxRetries) {
await this.delay(Math.pow(2, attempt) * 1000); // Exponential backoff
}
}
}
throw lastError;
}
```
---
## 📊 Sprint 2 Metrics
**Current State**:
- Unit tests: 80%+ coverage ✅
- Backend E2E: 40% coverage (4/10 modules)
- Frontend E2E: 0% coverage ❌
- Voice: 90% complete (missing error recovery)
**Sprint 2 Goal**:
- Backend E2E: 80% coverage (8/10 modules)
- Frontend E2E: 50% coverage (critical flows)
- Voice: 100% complete (full error recovery)
**Success Criteria**:
- All critical user journeys have E2E tests
- Voice commands have < 5% failure rate
- Test suite runs in < 5 minutes
- CI/CD pipeline includes all tests
---
## 🚀 Next Steps
1. **Decision**: Choose Option A, B, or C
2. **Setup**: Configure Playwright for frontend (if not done)
3. **Execute**: Implement tests module by module
4. **Validate**: Run full test suite
5. **Document**: Update test coverage reports
**Recommendation**: Start with **Option C (Hybrid)** for best ROI.
---
**Document Owner**: Development Team
**Last Updated**: October 3, 2025
**Next Review**: After Sprint 2 completion

View File

@@ -1,280 +0,0 @@
# AI Streaming Responses - Implementation Guide
## Overview
This document describes the implementation of streaming AI responses using Server-Sent Events (SSE) for real-time token-by-token display.
## Architecture
### Backend Components
**1. StreamingService** (`src/modules/ai/streaming/streaming.service.ts`)
- Handles Azure OpenAI streaming API
- Processes SSE stream from Azure
- Emits tokens via callback function
- Chunk types: `token`, `metadata`, `done`, `error`
**2. AI Controller** (`src/modules/ai/ai.controller.ts`)
- Endpoint: `POST /api/v1/ai/chat/stream`
- Headers: `Content-Type: text/event-stream`
- Streams response chunks to client
- Error handling with SSE events
**3. AI Service Integration** (TODO)
- Add `chatStream()` method to AIService
- Reuse existing safety checks and context building
- Call StreamingService for actual streaming
- Save conversation after completion
### Frontend Components (TODO)
**1. Streaming Hook** (`hooks/useStreamingChat.ts`)
```typescript
const { streamMessage, isStreaming } = useStreamingChat();
streamMessage(
{ message: "Hello", conversationId: "123" },
(chunk) => {
// Handle incoming chunks
if (chunk.type === 'token') {
appendToMessage(chunk.content);
}
}
);
```
**2. AIChatInterface Updates**
- Add streaming state management
- Display tokens as they arrive
- Show typing indicator during streaming
- Handle stream errors gracefully
## Implementation Steps
### Step 1: Complete Backend Integration (30 min)
1. Add StreamingService to AI module:
```typescript
// ai.module.ts
import { StreamingService } from './streaming/streaming.service';
@Module({
providers: [AIService, StreamingService, ...]
})
```
2. Implement `chatStream()` in AIService:
```typescript
async chatStream(
userId: string,
chatDto: ChatMessageDto,
callback: StreamCallback
): Promise<void> {
// 1. Run all safety checks (rate limit, input sanitization, etc.)
// 2. Build context messages
// 3. Call streamingService.streamCompletion()
// 4. Collect full response and save conversation
}
```
### Step 2: Frontend Streaming Client (1 hour)
1. Create EventSource hook:
```typescript
// hooks/useStreamingChat.ts
export function useStreamingChat() {
const streamMessage = async (
chatDto: ChatMessageDto,
onChunk: (chunk: StreamChunk) => void
) => {
const response = await fetch('/api/v1/ai/chat/stream', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(chatDto),
});
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
const lines = chunk.split('\n');
for (const line of lines) {
if (line.startsWith('data: ')) {
const data = JSON.parse(line.substring(6));
onChunk(data);
}
}
}
};
return { streamMessage };
}
```
2. Update AIChatInterface:
```typescript
const [streamingMessage, setStreamingMessage] = useState('');
const { streamMessage, isStreaming } = useStreamingChat();
const handleSubmit = async () => {
setStreamingMessage('');
setIsLoading(true);
await streamMessage(
{ message: input, conversationId },
(chunk) => {
if (chunk.type === 'token') {
setStreamingMessage(prev => prev + chunk.content);
} else if (chunk.type === 'done') {
// Add to messages array
setMessages(prev => [...prev, {
role: 'assistant',
content: streamingMessage
}]);
setStreamingMessage('');
setIsLoading(false);
}
}
);
};
```
### Step 3: UI Enhancements (30 min)
1. Add streaming indicator:
```tsx
{isStreaming && (
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
<CircularProgress size={16} />
<Typography variant="caption">AI is thinking...</Typography>
</Box>
)}
```
2. Show partial message:
```tsx
{streamingMessage && (
<Paper sx={{ p: 2, bgcolor: 'grey.100' }}>
<ReactMarkdown>{streamingMessage}</ReactMarkdown>
<Box component="span" sx={{ animation: 'blink 1s infinite' }}>|</Box>
</Paper>
)}
```
3. Add CSS animation:
```css
@keyframes blink {
0%, 100% { opacity: 1; }
50% { opacity: 0; }
}
```
## Testing
### Backend Test
```bash
curl -X POST http://localhost:3020/api/v1/ai/chat/stream \
-H "Content-Type: application/json" \
-d '{"message": "Tell me about baby sleep patterns"}' \
--no-buffer
```
Expected output:
```
data: {"type":"token","content":"Baby"}
data: {"type":"token","content":" sleep"}
data: {"type":"token","content":" patterns"}
...
data: {"type":"done"}
```
### Frontend Test
1. Open browser DevTools Network tab
2. Send a message in AI chat
3. Verify SSE connection established
4. Confirm tokens appear in real-time
## Performance Considerations
### Token Buffering
To reduce UI updates, buffer tokens:
```typescript
let buffer = '';
let bufferTimeout: NodeJS.Timeout;
onChunk((chunk) => {
if (chunk.type === 'token') {
buffer += chunk.content;
clearTimeout(bufferTimeout);
bufferTimeout = setTimeout(() => {
setStreamingMessage(prev => prev + buffer);
buffer = '';
}, 50); // Update every 50ms
}
});
```
### Memory Management
- Clear streaming state on unmount
- Cancel ongoing streams when switching conversations
- Limit message history to prevent memory leaks
### Error Recovery
- Retry connection on failure (max 3 attempts)
- Fall back to non-streaming on error
- Show user-friendly error messages
## Security
### Rate Limiting
- Streaming requests count against rate limits
- Close stream if rate limit exceeded mid-response
### Input Validation
- Same validation as non-streaming endpoint
- Safety checks before starting stream
### Connection Management
- Set timeout for inactive connections (60s)
- Clean up resources on client disconnect
## Future Enhancements
1. **Token Usage Tracking**: Track streaming token usage separately
2. **Pause/Resume**: Allow users to pause streaming
3. **Multi-Model Streaming**: Switch models mid-conversation
4. **Streaming Analytics**: Track average tokens/second
5. **WebSocket Alternative**: Consider WebSocket for bidirectional streaming
## Troubleshooting
### Stream Cuts Off Early
- Check timeout settings (increase to 120s for long responses)
- Verify nginx/proxy timeout configuration
- Check network connectivity
### Tokens Arrive Out of Order
- Ensure single-threaded processing
- Use buffer to accumulate before rendering
- Verify SSE event ordering
### High Latency
- Check Azure OpenAI endpoint latency
- Optimize context size to reduce time-to-first-token
- Consider caching common responses
## References
- [Azure OpenAI Streaming Docs](https://learn.microsoft.com/en-us/azure/ai-services/openai/how-to/streaming)
- [Server-Sent Events Spec](https://html.spec.whatwg.org/multipage/server-sent-events.html)
- [LangChain Streaming](https://js.langchain.com/docs/expression_language/streaming)

View File

@@ -1,526 +0,0 @@
# Testing Strategy - Maternal App
**Target Coverage:** 80%+ across all layers
**Testing Pyramid:** Unit (70%) → Integration (20%) → E2E (10%)
---
## 1. Backend Testing (NestJS)
### 1.1 Unit Tests (Target: 70% of tests)
**Tools:** Jest, @nestjs/testing
**What to Test:**
- **Services** (Business Logic)
- ComplianceService (data export, account deletion)
- AuthService (registration with COPPA validation, login, token management)
- ChildrenService (CRUD operations)
- TrackingService (activity creation, daily summary)
- AIService (chat, conversation memory)
- VoiceService (intent classification, entity extraction)
- EmbeddingsService (vector search, semantic memory)
- **Guards**
- JwtAuthGuard
- Public decorator
- **Pipes**
- ValidationPipe (DTO validation)
- **Utilities**
- Date calculations
- Age verification (COPPA compliance)
- Token generation
**Example Test Structure:**
```typescript
describe('ComplianceService', () => {
let service: ComplianceService;
let userRepository: Repository<User>;
beforeEach(async () => {
const module = await Test.createTestingModule({
providers: [
ComplianceService,
{ provide: getRepositoryToken(User), useClass: Repository },
],
}).compile();
service = module.get<ComplianceService>(ComplianceService);
});
it('should export user data with all entities', async () => {
// Test implementation
});
it('should schedule account deletion with 30-day grace period', async () => {
// Test implementation
});
});
```
### 1.2 Integration Tests (Target: 20% of tests)
**Tools:** Jest, Supertest, @nestjs/testing
**What to Test:**
- **API Endpoints** (Controller + Service + Database)
- POST /api/v1/compliance/data-export
- POST /api/v1/compliance/request-deletion
- POST /api/v1/auth/register (with COPPA validation)
- POST /api/v1/auth/login
- POST /api/v1/activities (tracking)
- POST /api/v1/ai/chat
- **Authentication Flows**
- Register → Login → Protected Route
- Register with COPPA (age 13-17)
- Register blocked (age < 13)
- **Database Operations**
- CRUD operations with real database
- Transaction rollbacks
- Cascade deletions
**Example Test Structure:**
```typescript
describe('ComplianceController (e2e)', () => {
let app: INestApplication;
let authToken: string;
beforeAll(async () => {
const moduleFixture = await Test.createTestingModule({
imports: [AppModule],
}).compile();
app = moduleFixture.createNestApplication();
await app.init();
});
it('/api/v1/compliance/data-export (GET)', () => {
return request(app.getHttpServer())
.get('/api/v1/compliance/data-export')
.set('Authorization', `Bearer ${authToken}`)
.expect(200)
.expect((res) => {
expect(res.body.data).toHaveProperty('user');
expect(res.body.data).toHaveProperty('children');
expect(res.body.data).toHaveProperty('activities');
});
});
});
```
---
## 2. Frontend Testing (Next.js + React)
### 2.1 Unit Tests (Component Testing)
**Tools:** Jest, React Testing Library, @testing-library/user-event
**What to Test:**
- **Components**
- DataExport component (button click, download trigger)
- AccountDeletion component (dialog flow, deletion request)
- Registration form (COPPA age validation, form submission)
- Settings page (profile update, compliance sections)
- Tracking forms (feeding, sleep, diaper)
- **Redux Slices**
- authSlice (login, logout, token refresh)
- childrenSlice (CRUD operations)
- activitiesSlice (create, update, delete)
- offlineSlice (sync queue, conflict resolution)
- **API Clients**
- complianceApi (all methods)
- authApi, childrenApi, trackingApi
- **Utilities**
- Date formatting
- Age calculation
- Token storage
**Example Test Structure:**
```typescript
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { DataExport } from '@/components/settings/DataExport';
import { complianceApi } from '@/lib/api/compliance';
jest.mock('@/lib/api/compliance');
describe('DataExport Component', () => {
it('should download user data when button is clicked', async () => {
const mockDownload = jest.fn();
(complianceApi.downloadUserData as jest.Mock) = mockDownload;
render(<DataExport />);
const button = screen.getByText('Download My Data');
fireEvent.click(button);
await waitFor(() => {
expect(mockDownload).toHaveBeenCalledTimes(1);
});
expect(screen.getByText('Your data has been downloaded successfully!')).toBeInTheDocument();
});
it('should show error message on download failure', async () => {
(complianceApi.downloadUserData as jest.Mock).mockRejectedValue(
new Error('Network error')
);
render(<DataExport />);
fireEvent.click(screen.getByText('Download My Data'));
await waitFor(() => {
expect(screen.getByText(/Failed to export data/)).toBeInTheDocument();
});
});
});
```
### 2.2 Integration Tests (API Interaction)
**What to Test:**
- Form submission with API calls
- Authentication flows
- Error handling and retry logic
- Optimistic updates with Redux
---
## 3. End-to-End Tests (Target: 10% of tests)
**Tools:** Playwright
**Critical User Journeys:**
### 3.1 Registration & COPPA Compliance
```typescript
test('User under 13 cannot register', async ({ page }) => {
await page.goto('/register');
await page.fill('[name="name"]', 'John Doe');
await page.fill('[name="email"]', 'john@example.com');
await page.fill('[name="dateOfBirth"]', '2015-01-01'); // 9 years old
await page.fill('[name="password"]', 'SecurePass123');
await page.fill('[name="confirmPassword"]', 'SecurePass123');
await page.check('[name="agreeToTerms"]');
await page.check('[name="agreeToPrivacy"]');
await page.click('button[type="submit"]');
await expect(page.locator('text=/Users under 13/')).toBeVisible();
});
test('User 13-17 requires parental consent', async ({ page }) => {
await page.goto('/register');
await page.fill('[name="dateOfBirth"]', '2010-01-01'); // 14 years old
// Parental email field should appear
await expect(page.locator('[name="parentalEmail"]')).toBeVisible();
await expect(page.locator('text=/parental consent/')).toBeVisible();
});
```
### 3.2 Account Deletion Flow
```typescript
test('User can request account deletion and cancel it', async ({ page }) => {
// Login
await login(page, 'user@example.com', 'password');
// Navigate to settings
await page.goto('/settings');
// Request deletion
await page.click('text=Delete My Account');
await page.fill('[name="reason"]', 'Testing deletion flow');
await page.click('button:has-text("Delete Account")');
// Verify deletion scheduled
await expect(page.locator('text=/Account deletion scheduled/')).toBeVisible();
// Cancel deletion
await page.click('text=Cancel Deletion Request');
await page.click('button:has-text("Cancel Deletion")');
// Verify cancellation
await expect(page.locator('text=/cancelled successfully/')).toBeVisible();
});
```
### 3.3 Data Export Flow
```typescript
test('User can export their data', async ({ page }) => {
await login(page, 'user@example.com', 'password');
await page.goto('/settings');
const [download] = await Promise.all([
page.waitForEvent('download'),
page.click('text=Download My Data')
]);
expect(download.suggestedFilename()).toMatch(/maternal-app-data-export.*\.json/);
});
```
### 3.4 Activity Tracking Flow
```typescript
test('User can track feeding activity', async ({ page }) => {
await login(page, 'user@example.com', 'password');
await page.goto('/track/feeding');
await page.selectOption('[name="childId"]', { index: 0 });
await page.fill('[name="amount"]', '120');
await page.selectOption('[name="unit"]', 'ml');
await page.click('button:has-text("Save")');
await expect(page.locator('text=/Activity saved/')).toBeVisible();
// Verify on dashboard
await page.goto('/');
await expect(page.locator('text=/Feeding/')).toBeVisible();
});
```
---
## 4. Code Coverage Goals
### 4.1 Overall Targets
- **Total Coverage:** 80%+
- **Statements:** 80%+
- **Branches:** 75%+
- **Functions:** 80%+
- **Lines:** 80%+
### 4.2 Module-Specific Targets
**Backend:**
- Auth Module: 90%+ (critical security)
- Compliance Module: 95%+ (legal requirement)
- Tracking Module: 85%+
- AI Module: 80%+
- Voice Module: 80%+
**Frontend:**
- Compliance Components: 95%+
- Auth Components: 90%+
- Tracking Components: 85%+
- API Clients: 90%+
- Redux Slices: 85%+
---
## 5. CI/CD Integration
### 5.1 GitHub Actions Workflow
**Triggers:**
- Push to main branch
- Pull request to main
- Scheduled nightly runs
**Steps:**
1. Checkout code
2. Setup Node.js (v20)
3. Install dependencies
4. Run linter (ESLint)
5. Run backend unit tests
6. Run backend integration tests
7. Run frontend tests
8. Run E2E tests
9. Generate coverage reports
10. Upload coverage to Codecov
11. Fail PR if coverage drops below 80%
**Example `.github/workflows/test.yml`:**
```yaml
name: Test Suite
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
backend-tests:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:15
env:
POSTGRES_PASSWORD: test
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '20'
- run: npm ci
- run: npm test -- --coverage
- uses: codecov/codecov-action@v3
frontend-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- run: npm ci
- run: npm test -- --coverage
e2e-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- run: npx playwright install --with-deps
- run: npm run test:e2e
```
---
## 6. Test Data Management
### 6.1 Test Database
- Use separate test database
- Seed with test fixtures
- Clean between tests
### 6.2 Test Fixtures
- Create factory functions for test data
- Predefined users, children, activities
- COPPA-compliant test scenarios (various ages)
**Example:**
```typescript
export const testUsers = {
adult: {
name: 'Adult User',
email: 'adult@example.com',
dateOfBirth: '1990-01-01',
},
minor14: {
name: 'Teen User',
email: 'teen@example.com',
dateOfBirth: '2010-01-01',
parentalEmail: 'parent@example.com',
coppaConsentGiven: true,
},
child12: {
name: 'Child User',
email: 'child@example.com',
dateOfBirth: '2012-01-01', // Should be blocked
},
};
```
---
## 7. Testing Best Practices
### 7.1 General Principles
- **AAA Pattern:** Arrange, Act, Assert
- **DRY:** Don't Repeat Yourself (use factories and helpers)
- **Fast:** Keep unit tests under 100ms
- **Isolated:** No dependencies between tests
- **Deterministic:** Same input = same output
### 7.2 Mocking Strategy
- Mock external services (Azure OpenAI, Mailgun, MinIO)
- Mock time-dependent functions
- Use in-memory database for unit tests
- Real database for integration tests
### 7.3 Naming Conventions
```typescript
describe('ServiceName', () => {
describe('methodName', () => {
it('should do something when condition', () => {
// Test
});
it('should throw error when invalid input', () => {
// Test
});
});
});
```
---
## 8. Continuous Improvement
### 8.1 Metrics to Track
- Code coverage percentage
- Test execution time
- Flaky test rate
- Bug escape rate
### 8.2 Review Process
- All PRs must have tests
- Coverage must not decrease
- CI must pass before merge
---
## 9. Implementation Timeline
**Week 1:**
- ✅ Setup Jest for backend and frontend
- ✅ Create first unit tests (Compliance, Auth)
- ✅ Setup test database
**Week 2:**
- ✅ Create integration tests for critical endpoints
- ✅ Setup Playwright for E2E
- ✅ Create E2E tests for COPPA flows
**Week 3:**
- ✅ Expand coverage to 50%+
- ✅ Setup CI/CD pipeline
- ✅ Configure coverage reporting
**Week 4:**
- ✅ Reach 80%+ coverage
- ✅ Optimize test performance
- ✅ Documentation and training
---
## 10. Quick Start Commands
```bash
# Backend
cd maternal-app-backend
npm test # Run all tests
npm test -- --coverage # With coverage
npm test -- --watch # Watch mode
npm run test:e2e # Integration tests
# Frontend
cd maternal-web
npm test # Run all tests
npm test -- --coverage # With coverage
npm test -- --watch # Watch mode
npm run test:e2e # E2E with Playwright
# Coverage Reports
npm test -- --coverage --coverageReporters=html
# Open coverage/index.html in browser
```
---
## Status: IN PROGRESS
**Current Coverage:** 0%
**Target Coverage:** 80%+
**Estimated Completion:** 3-4 weeks

View File

@@ -1,576 +0,0 @@
# Azure OpenAI Integration - Implementation Summary
## Overview
The AI service has been updated to support both OpenAI and Azure OpenAI with automatic fallback, proper environment configuration, and full support for GPT-5 models including reasoning tokens.
---
## Environment Configuration
### ✅ Complete Environment Variables (.env)
```bash
# AI Services Configuration
# Primary provider: 'openai' or 'azure'
AI_PROVIDER=azure
# OpenAI Configuration (Primary - if AI_PROVIDER=openai)
OPENAI_API_KEY=sk-your-openai-api-key-here
OPENAI_MODEL=gpt-4o-mini
OPENAI_EMBEDDING_MODEL=text-embedding-3-small
OPENAI_MAX_TOKENS=1000
# Azure OpenAI Configuration (if AI_PROVIDER=azure)
AZURE_OPENAI_ENABLED=true
# Azure OpenAI - Chat/Completion Endpoint (GPT-5)
# Each deployment has its own API key for better security and quota management
AZURE_OPENAI_CHAT_ENDPOINT=https://footprints-open-ai.openai.azure.com
AZURE_OPENAI_CHAT_DEPLOYMENT=gpt-5-mini
AZURE_OPENAI_CHAT_API_VERSION=2025-04-01-preview
AZURE_OPENAI_CHAT_API_KEY=your-chat-api-key-here
AZURE_OPENAI_CHAT_MAX_TOKENS=1000
AZURE_OPENAI_REASONING_EFFORT=medium
# Azure OpenAI - Whisper/Voice Endpoint
AZURE_OPENAI_WHISPER_ENDPOINT=https://footprints-open-ai.openai.azure.com
AZURE_OPENAI_WHISPER_DEPLOYMENT=whisper
AZURE_OPENAI_WHISPER_API_VERSION=2025-04-01-preview
AZURE_OPENAI_WHISPER_API_KEY=your-whisper-api-key-here
# Azure OpenAI - Embeddings Endpoint
AZURE_OPENAI_EMBEDDINGS_ENDPOINT=https://footprints-ai.openai.azure.com
AZURE_OPENAI_EMBEDDINGS_DEPLOYMENT=Text-Embedding-ada-002-V2
AZURE_OPENAI_EMBEDDINGS_API_VERSION=2023-05-15
AZURE_OPENAI_EMBEDDINGS_API_KEY=your-embeddings-api-key-here
```
### Configuration for Your Setup
Based on your requirements:
```bash
AI_PROVIDER=azure
AZURE_OPENAI_ENABLED=true
# Chat (GPT-5 Mini) - Separate API key
AZURE_OPENAI_CHAT_ENDPOINT=https://footprints-open-ai.openai.azure.com
AZURE_OPENAI_CHAT_DEPLOYMENT=gpt-5-mini
AZURE_OPENAI_CHAT_API_VERSION=2025-04-01-preview
AZURE_OPENAI_CHAT_API_KEY=[your_chat_key]
AZURE_OPENAI_REASONING_EFFORT=medium # or 'minimal', 'low', 'high'
# Voice (Whisper) - Separate API key
AZURE_OPENAI_WHISPER_ENDPOINT=https://footprints-open-ai.openai.azure.com
AZURE_OPENAI_WHISPER_DEPLOYMENT=whisper
AZURE_OPENAI_WHISPER_API_VERSION=2025-04-01-preview
AZURE_OPENAI_WHISPER_API_KEY=[your_whisper_key]
# Embeddings - Separate API key
AZURE_OPENAI_EMBEDDINGS_ENDPOINT=https://footprints-ai.openai.azure.com
AZURE_OPENAI_EMBEDDINGS_DEPLOYMENT=Text-Embedding-ada-002-V2
AZURE_OPENAI_EMBEDDINGS_API_VERSION=2023-05-15
AZURE_OPENAI_EMBEDDINGS_API_KEY=[your_embeddings_key]
```
### Why Separate API Keys?
Each Azure OpenAI deployment can have its own API key for:
- **Security**: Limit blast radius if a key is compromised
- **Quota Management**: Separate rate limits per service
- **Cost Tracking**: Monitor usage per deployment
- **Access Control**: Different team members can have access to different services
---
## AI Service Implementation
### ✅ Key Features
**1. Multi-Provider Support**
- Primary: Azure OpenAI (GPT-5)
- Fallback: OpenAI (GPT-4o-mini)
- Automatic failover if Azure unavailable
**2. GPT-5 Specific Features**
- ✅ Reasoning tokens tracking
- ✅ Configurable reasoning effort (minimal, low, medium, high)
- ✅ Extended context (272K input + 128K output = 400K total)
- ✅ Response metadata with token counts
**3. Response Format**
```typescript
interface ChatResponseDto {
conversationId: string;
message: string;
timestamp: Date;
metadata?: {
model?: string; // 'gpt-5-mini' or 'gpt-4o-mini'
provider?: 'openai' | 'azure';
reasoningTokens?: number; // GPT-5 only
totalTokens?: number;
};
}
```
**4. Azure GPT-5 Request**
```typescript
const requestBody = {
messages: azureMessages,
temperature: 0.7,
max_tokens: 1000,
stream: false,
reasoning_effort: 'medium', // GPT-5 specific
};
```
**5. Azure GPT-5 Response**
```typescript
{
choices: [{
message: { content: string },
reasoning_tokens: number, // NEW in GPT-5
}],
usage: {
prompt_tokens: number,
completion_tokens: number,
reasoning_tokens: number, // NEW in GPT-5
total_tokens: number,
}
}
```
---
## GPT-5 vs GPT-4 Differences
### Reasoning Tokens
**GPT-5 introduces `reasoning_tokens`**:
- Hidden tokens used for internal reasoning
- Not part of message content
- Configurable via `reasoning_effort` parameter
- Higher effort = more reasoning tokens = better quality
**Reasoning Effort Levels**:
```typescript
'minimal' // Fastest, lowest reasoning tokens
'low' // Quick responses with basic reasoning
'medium' // Balanced (default)
'high' // Most thorough, highest reasoning tokens
```
### Context Length
**GPT-5**:
- Input: 272,000 tokens (vs GPT-4's 128K)
- Output: 128,000 tokens
- Total context: 400,000 tokens
**GPT-4o**:
- Input: 128,000 tokens
- Total context: 128,000 tokens
### Token Efficiency
**GPT-5 Benefits**:
- 22% fewer output tokens vs o3
- 45% fewer tool calls
- Better performance per dollar despite reasoning overhead
### Pricing
**Azure OpenAI GPT-5**:
- Input: $1.25 / 1M tokens
- Output: $10.00 / 1M tokens
- Cached input: $0.125 / 1M (90% discount for repeated prompts)
---
## Implementation Details
### Service Initialization
The AI service now:
1. Checks `AI_PROVIDER` environment variable
2. Configures Azure OpenAI if provider is 'azure'
3. Falls back to OpenAI if Azure not configured
4. Logs which provider is active
```typescript
constructor() {
this.aiProvider = this.configService.get('AI_PROVIDER', 'openai');
if (this.aiProvider === 'azure') {
// Load Azure configuration from environment
this.azureChatEndpoint = this.configService.get('AZURE_OPENAI_CHAT_ENDPOINT');
this.azureChatDeployment = this.configService.get('AZURE_OPENAI_CHAT_DEPLOYMENT');
// ... more configuration
} else {
// Load OpenAI configuration
this.chatModel = new ChatOpenAI({ ... });
}
}
```
### Chat Method Flow
```typescript
async chat(userId, chatDto) {
// 1. Validate configuration
// 2. Get/create conversation
// 3. Build context with user data
// 4. Generate response based on provider:
if (this.aiProvider === 'azure') {
const response = await this.generateWithAzure(messages);
// Returns: { content, reasoningTokens, totalTokens }
} else {
const response = await this.generateWithOpenAI(messages);
// Returns: content string
}
// 5. Save conversation with token tracking
// 6. Return response with metadata
}
```
### Azure Generation Method
```typescript
private async generateWithAzure(messages) {
const url = `${endpoint}/openai/deployments/${deployment}/chat/completions?api-version=${apiVersion}`;
const requestBody = {
messages: azureMessages,
temperature: 0.7,
max_tokens: 1000,
reasoning_effort: 'medium', // GPT-5 parameter
};
const response = await axios.post(url, requestBody, {
headers: {
'api-key': this.azureApiKey,
'Content-Type': 'application/json',
},
});
return {
content: response.data.choices[0].message.content,
reasoningTokens: response.data.usage.reasoning_tokens,
totalTokens: response.data.usage.total_tokens,
};
}
```
### Automatic Fallback
If Azure fails, the service automatically retries with OpenAI:
```typescript
catch (error) {
// Fallback to OpenAI if Azure fails
if (this.aiProvider === 'azure' && this.chatModel) {
this.logger.warn('Azure OpenAI failed, attempting OpenAI fallback...');
this.aiProvider = 'openai';
return this.chat(userId, chatDto); // Recursive call with OpenAI
}
throw new BadRequestException('Failed to generate AI response');
}
```
---
## Testing the Integration
### 1. Check Provider Status
```bash
GET /api/v1/ai/provider-status
```
Response:
```json
{
"provider": "azure",
"model": "gpt-5-mini",
"configured": true,
"endpoint": "https://footprints-open-ai.openai.azure.com"
}
```
### 2. Test Chat with GPT-5
```bash
POST /api/v1/ai/chat
Authorization: Bearer {token}
{
"message": "How much should a 3-month-old eat per feeding?"
}
```
Response:
```json
{
"conversationId": "conv_123",
"message": "A 3-month-old typically eats...",
"timestamp": "2025-01-15T10:30:00Z",
"metadata": {
"model": "gpt-5-mini",
"provider": "azure",
"reasoningTokens": 145,
"totalTokens": 523
}
}
```
### 3. Monitor Reasoning Tokens
Check logs for GPT-5 reasoning token usage:
```
[AIService] Azure OpenAI response: {
model: 'gpt-5-mini',
finish_reason: 'stop',
prompt_tokens: 256,
completion_tokens: 122,
reasoning_tokens: 145, // GPT-5 reasoning overhead
total_tokens: 523
}
```
---
## Optimizing Reasoning Effort
### When to Use Each Level
**Minimal** (`reasoning_effort: 'minimal'`):
- Simple queries
- Quick responses needed
- Cost optimization
- Use case: "What time is it?"
**Low** (`reasoning_effort: 'low'`):
- Straightforward questions
- Fast turnaround required
- Use case: "How many oz in 120ml?"
**Medium** (`reasoning_effort: 'medium'`) - **Default**:
- Balanced performance
- Most common use cases
- Use case: "Is my baby's sleep pattern normal?"
**High** (`reasoning_effort: 'high'`):
- Complex reasoning required
- Premium features
- Use case: "Analyze my baby's feeding patterns over the last month and suggest optimizations"
### Dynamic Reasoning Effort
You can adjust based on query complexity:
```typescript
// Future enhancement: Analyze query complexity
const effort = this.determineReasoningEffort(chatDto.message);
const requestBody = {
messages: azureMessages,
reasoning_effort: effort, // Dynamic based on query
};
```
---
## Future Enhancements
### 1. Voice Service (Whisper)
Implement similar pattern for voice transcription:
```typescript
export class WhisperService {
async transcribeAudio(audioBuffer: Buffer): Promise<string> {
if (this.aiProvider === 'azure') {
return this.transcribeWithAzure(audioBuffer);
}
return this.transcribeWithOpenAI(audioBuffer);
}
private async transcribeWithAzure(audioBuffer: Buffer) {
const url = `${this.azureWhisperEndpoint}/openai/deployments/${this.azureWhisperDeployment}/audio/transcriptions?api-version=${this.azureWhisperApiVersion}`;
const formData = new FormData();
formData.append('file', new Blob([audioBuffer]), 'audio.wav');
const response = await axios.post(url, formData, {
headers: {
'api-key': this.azureWhisperApiKey, // Separate key for Whisper
},
});
return response.data.text;
}
}
```
### 2. Embeddings Service
For pattern recognition and similarity search:
```typescript
export class EmbeddingsService {
async createEmbedding(text: string): Promise<number[]> {
if (this.aiProvider === 'azure') {
return this.createEmbeddingWithAzure(text);
}
return this.createEmbeddingWithOpenAI(text);
}
private async createEmbeddingWithAzure(text: string) {
const url = `${this.azureEmbeddingsEndpoint}/openai/deployments/${this.azureEmbeddingsDeployment}/embeddings?api-version=${this.azureEmbeddingsApiVersion}`;
const response = await axios.post(url, { input: text }, {
headers: {
'api-key': this.azureEmbeddingsApiKey, // Separate key for Embeddings
},
});
return response.data.data[0].embedding;
}
}
```
### 3. Prompt Caching
Leverage Azure's cached input pricing (90% discount):
```typescript
// Reuse identical system prompts for cost savings
const systemPrompt = `You are a helpful parenting assistant...`; // Cache this
```
### 4. Streaming Responses
For better UX with long responses:
```typescript
const requestBody = {
messages: azureMessages,
stream: true, // Enable streaming
reasoning_effort: 'medium',
};
// Handle streamed response
```
---
## Troubleshooting
### Common Issues
**1. "AI service not configured"**
- Check `AI_PROVIDER` is set to 'azure'
- Verify `AZURE_OPENAI_CHAT_API_KEY` is set (not the old `AZURE_OPENAI_API_KEY`)
- Confirm `AZURE_OPENAI_CHAT_ENDPOINT` is correct
**2. "Invalid API version"**
- GPT-5 requires `2025-04-01-preview` or later
- Update `AZURE_OPENAI_CHAT_API_VERSION`
**3. "Deployment not found"**
- Verify `AZURE_OPENAI_CHAT_DEPLOYMENT` matches Azure deployment name
- Check deployment is in same region as endpoint
**4. High token usage**
- GPT-5 reasoning tokens are additional overhead
- Reduce `reasoning_effort` if cost is concern
- Use `'minimal'` for simple queries
**5. Slow responses**
- Higher `reasoning_effort` = slower responses
- Use `'low'` or `'minimal'` for time-sensitive queries
- Consider caching common responses
### Debug Logging
Enable debug logs to see requests/responses:
```typescript
this.logger.debug('Azure OpenAI request:', {
url,
deployment,
reasoning_effort,
messageCount,
});
this.logger.debug('Azure OpenAI response:', {
model,
finish_reason,
prompt_tokens,
completion_tokens,
reasoning_tokens,
total_tokens,
});
```
---
## Summary
**Fully Configured**:
- Environment variables for all Azure endpoints
- Chat (GPT-5), Whisper, Embeddings separately configurable
- No hardcoded values
**GPT-5 Support**:
- Reasoning tokens tracked and returned
- Configurable reasoning effort (minimal/low/medium/high)
- Extended 400K context window ready
**Automatic Fallback**:
- Azure → OpenAI if Azure fails
- Graceful degradation
**Monitoring**:
- Detailed logging for debugging
- Token usage tracking (including reasoning tokens)
- Provider status endpoint
**Production Ready**:
- Proper error handling
- Timeout configuration (30s)
- Metadata in responses
---
## Next Steps
1. **Add your actual API keys** to `.env`:
```bash
AZURE_OPENAI_CHAT_API_KEY=[your_chat_key]
AZURE_OPENAI_WHISPER_API_KEY=[your_whisper_key]
AZURE_OPENAI_EMBEDDINGS_API_KEY=[your_embeddings_key]
```
2. **Restart the backend** to pick up configuration:
```bash
npm run start:dev
```
3. **Test the integration**:
- Check provider status endpoint
- Send a test chat message
- Verify reasoning tokens in response
4. **Monitor token usage**:
- Review logs for reasoning token counts
- Adjust `reasoning_effort` based on usage patterns
- Consider cost optimization strategies
5. **Implement Voice & Embeddings** (optional):
- Follow similar patterns as chat service
- Use separate Azure endpoints already configured

View File

@@ -1,481 +0,0 @@
# Azure OpenAI Integration Guide
## Overview
This guide details the integration of Azure OpenAI services as a fallback option when OpenAI APIs are unavailable. The application supports both OpenAI and Azure OpenAI endpoints with automatic failover.
## Configuration
### Environment Variables
Add the following to your `.env` file:
```env
# OpenAI Configuration (Primary)
OPENAI_API_KEY=your_openai_key
OPENAI_MODEL=gpt-4o
OPENAI_EMBEDDING_MODEL=text-embedding-3-small
# Azure OpenAI Configuration (Fallback)
AZURE_OPENAI_ENABLED=true
AZURE_OPENAI_API_KEY=your_azure_key
# Chat Endpoint
AZURE_OPENAI_CHAT_ENDPOINT=https://footprints-open-ai.openai.azure.com
AZURE_OPENAI_CHAT_DEPLOYMENT=gpt-5-mini
AZURE_OPENAI_CHAT_API_VERSION=2025-04-01-preview
# Voice/Whisper Endpoint
AZURE_OPENAI_WHISPER_ENDPOINT=https://footprints-open-ai.openai.azure.com
AZURE_OPENAI_WHISPER_DEPLOYMENT=whisper
AZURE_OPENAI_WHISPER_API_VERSION=2025-04-01-preview
# Embeddings Endpoint
AZURE_OPENAI_EMBEDDINGS_ENDPOINT=https://footprints-ai.openai.azure.com
AZURE_OPENAI_EMBEDDINGS_DEPLOYMENT=Text-Embedding-ada-002-V2
AZURE_OPENAI_EMBEDDINGS_API_VERSION=2023-05-15
```
## Implementation
### Phase 3: Voice Input Integration (Whisper)
Update the Voice Service to support Azure OpenAI Whisper:
```typescript
// src/modules/voice/services/whisper.service.ts
import { Injectable, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import OpenAI from 'openai';
import axios from 'axios';
@Injectable()
export class WhisperService {
private readonly logger = new Logger(WhisperService.name);
private openai: OpenAI;
private azureEnabled: boolean;
constructor(private configService: ConfigService) {
// Initialize OpenAI client
this.openai = new OpenAI({
apiKey: this.configService.get('OPENAI_API_KEY'),
});
this.azureEnabled = this.configService.get('AZURE_OPENAI_ENABLED') === 'true';
}
async transcribeAudio(audioBuffer: Buffer, language?: string): Promise<string> {
try {
// Try OpenAI first
return await this.transcribeWithOpenAI(audioBuffer, language);
} catch (error) {
this.logger.warn('OpenAI transcription failed, trying Azure OpenAI', error.message);
if (this.azureEnabled) {
return await this.transcribeWithAzure(audioBuffer, language);
}
throw error;
}
}
private async transcribeWithOpenAI(audioBuffer: Buffer, language?: string): Promise<string> {
const file = new File([audioBuffer], 'audio.wav', { type: 'audio/wav' });
const response = await this.openai.audio.transcriptions.create({
file,
model: 'whisper-1',
language: language || 'en',
});
return response.text;
}
private async transcribeWithAzure(audioBuffer: Buffer, language?: string): Promise<string> {
const endpoint = this.configService.get('AZURE_OPENAI_WHISPER_ENDPOINT');
const deployment = this.configService.get('AZURE_OPENAI_WHISPER_DEPLOYMENT');
const apiVersion = this.configService.get('AZURE_OPENAI_WHISPER_API_VERSION');
const apiKey = this.configService.get('AZURE_OPENAI_API_KEY');
const url = `${endpoint}/openai/deployments/${deployment}/audio/transcriptions?api-version=${apiVersion}`;
const formData = new FormData();
formData.append('file', new Blob([audioBuffer]), 'audio.wav');
if (language) {
formData.append('language', language);
}
const response = await axios.post(url, formData, {
headers: {
'api-key': apiKey,
'Content-Type': 'multipart/form-data',
},
});
return response.data.text;
}
}
```
### Phase 4: AI Assistant (Chat Completion)
Update the AI Service to support Azure OpenAI chat with GPT-5 models:
```typescript
// src/modules/ai/services/ai.service.ts
import { Injectable, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import OpenAI from 'openai';
import axios from 'axios';
@Injectable()
export class AIService {
private readonly logger = new Logger(AIService.name);
private openai: OpenAI;
private azureEnabled: boolean;
constructor(private configService: ConfigService) {
this.openai = new OpenAI({
apiKey: this.configService.get('OPENAI_API_KEY'),
});
this.azureEnabled = this.configService.get('AZURE_OPENAI_ENABLED') === 'true';
}
async generateResponse(
messages: Array<{ role: string; content: string }>,
temperature: number = 0.7,
): Promise<string> {
try {
// Try OpenAI first
return await this.generateWithOpenAI(messages, temperature);
} catch (error) {
this.logger.warn('OpenAI chat failed, trying Azure OpenAI', error.message);
if (this.azureEnabled) {
return await this.generateWithAzure(messages, temperature);
}
throw error;
}
}
private async generateWithOpenAI(
messages: Array<{ role: string; content: string }>,
temperature: number,
): Promise<string> {
const response = await this.openai.chat.completions.create({
model: this.configService.get('OPENAI_MODEL', 'gpt-4o'),
messages: messages as any,
temperature,
max_tokens: 1000,
});
return response.choices[0].message.content;
}
private async generateWithAzure(
messages: Array<{ role: string; content: string }>,
temperature: number,
): Promise<string> {
const endpoint = this.configService.get('AZURE_OPENAI_CHAT_ENDPOINT');
const deployment = this.configService.get('AZURE_OPENAI_CHAT_DEPLOYMENT');
const apiVersion = this.configService.get('AZURE_OPENAI_CHAT_API_VERSION');
const apiKey = this.configService.get('AZURE_OPENAI_API_KEY');
// NOTE: GPT-5 models use a different API format than GPT-4
// The response structure includes additional metadata
const url = `${endpoint}/openai/deployments/${deployment}/chat/completions?api-version=${apiVersion}`;
const response = await axios.post(
url,
{
messages,
temperature,
max_tokens: 1000,
// GPT-5 specific parameters
stream: false,
// Optional GPT-5 features:
// reasoning_effort: 'medium', // 'low', 'medium', 'high'
// response_format: { type: 'text' }, // or 'json_object' for structured output
},
{
headers: {
'api-key': apiKey,
'Content-Type': 'application/json',
},
},
);
// GPT-5 response structure may include reasoning tokens
// Extract the actual message content
return response.data.choices[0].message.content;
}
}
```
### Phase 5: Pattern Recognition (Embeddings)
Update the Embeddings Service for pattern analysis:
```typescript
// src/modules/analytics/services/embeddings.service.ts
import { Injectable, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import OpenAI from 'openai';
import axios from 'axios';
@Injectable()
export class EmbeddingsService {
private readonly logger = new Logger(EmbeddingsService.name);
private openai: OpenAI;
private azureEnabled: boolean;
constructor(private configService: ConfigService) {
this.openai = new OpenAI({
apiKey: this.configService.get('OPENAI_API_KEY'),
});
this.azureEnabled = this.configService.get('AZURE_OPENAI_ENABLED') === 'true';
}
async createEmbedding(text: string): Promise<number[]> {
try {
// Try OpenAI first
return await this.createEmbeddingWithOpenAI(text);
} catch (error) {
this.logger.warn('OpenAI embeddings failed, trying Azure OpenAI', error.message);
if (this.azureEnabled) {
return await this.createEmbeddingWithAzure(text);
}
throw error;
}
}
private async createEmbeddingWithOpenAI(text: string): Promise<number[]> {
const response = await this.openai.embeddings.create({
model: this.configService.get('OPENAI_EMBEDDING_MODEL', 'text-embedding-3-small'),
input: text,
});
return response.data[0].embedding;
}
private async createEmbeddingWithAzure(text: string): Promise<number[]> {
const endpoint = this.configService.get('AZURE_OPENAI_EMBEDDINGS_ENDPOINT');
const deployment = this.configService.get('AZURE_OPENAI_EMBEDDINGS_DEPLOYMENT');
const apiVersion = this.configService.get('AZURE_OPENAI_EMBEDDINGS_API_VERSION');
const apiKey = this.configService.get('AZURE_OPENAI_API_KEY');
const url = `${endpoint}/openai/deployments/${deployment}/embeddings?api-version=${apiVersion}`;
const response = await axios.post(
url,
{
input: text,
},
{
headers: {
'api-key': apiKey,
'Content-Type': 'application/json',
},
},
);
return response.data.data[0].embedding;
}
async calculateSimilarity(embedding1: number[], embedding2: number[]): Promise<number> {
// Cosine similarity calculation
const dotProduct = embedding1.reduce((sum, val, i) => sum + val * embedding2[i], 0);
const magnitude1 = Math.sqrt(embedding1.reduce((sum, val) => sum + val * val, 0));
const magnitude2 = Math.sqrt(embedding2.reduce((sum, val) => sum + val * val, 0));
return dotProduct / (magnitude1 * magnitude2);
}
}
```
## GPT-5 Model Differences
### Key Changes from GPT-4
1. **Reasoning Capabilities**: GPT-5 includes enhanced reasoning with configurable effort levels
- `reasoning_effort`: 'low' | 'medium' | 'high'
- Higher effort levels produce more thorough, step-by-step reasoning
2. **Response Metadata**: GPT-5 responses may include reasoning tokens
```typescript
{
choices: [{
message: { content: string },
reasoning_tokens: number, // New in GPT-5
finish_reason: string
}],
usage: {
prompt_tokens: number,
completion_tokens: number,
reasoning_tokens: number, // New in GPT-5
total_tokens: number
}
}
```
3. **Structured Output**: Enhanced JSON mode support
```typescript
{
response_format: {
type: 'json_schema',
json_schema: {
name: 'response',
schema: { /* your schema */ }
}
}
}
```
4. **API Version**: Use `2025-04-01-preview` for GPT-5 features
## Testing
### Unit Tests
```typescript
// src/modules/ai/__tests__/ai.service.spec.ts
describe('AIService', () => {
describe('Azure OpenAI Fallback', () => {
it('should fallback to Azure when OpenAI fails', async () => {
// Mock OpenAI failure
mockOpenAI.chat.completions.create.mockRejectedValue(new Error('API Error'));
// Mock Azure success
mockAxios.post.mockResolvedValue({
data: {
choices: [{ message: { content: 'Response from Azure' } }]
}
});
const result = await aiService.generateResponse([
{ role: 'user', content: 'Hello' }
]);
expect(result).toBe('Response from Azure');
expect(mockAxios.post).toHaveBeenCalledWith(
expect.stringContaining('gpt-5-mini'),
expect.any(Object),
expect.any(Object)
);
});
});
});
```
## Error Handling
```typescript
// src/common/exceptions/ai-service.exception.ts
export class AIServiceException extends HttpException {
constructor(
message: string,
public provider: 'openai' | 'azure',
public originalError?: Error,
) {
super(
{
statusCode: HttpStatus.SERVICE_UNAVAILABLE,
error: 'AI_SERVICE_UNAVAILABLE',
message,
provider,
},
HttpStatus.SERVICE_UNAVAILABLE,
);
}
}
```
## Monitoring
Add logging for failover events:
```typescript
// Log when failover occurs
this.logger.warn('OpenAI service unavailable, switching to Azure OpenAI', {
endpoint: 'chat',
model: deployment,
requestId: context.requestId,
});
// Track usage metrics
this.metricsService.increment('ai.provider.azure.requests');
this.metricsService.increment('ai.provider.openai.failures');
```
## Cost Optimization
1. **Primary/Fallback Strategy**: Use OpenAI as primary to take advantage of potentially lower costs
2. **Rate Limiting**: Implement exponential backoff before failover
3. **Circuit Breaker**: After 5 consecutive failures, switch primary provider temporarily
4. **Token Tracking**: Monitor token usage across both providers
```typescript
// src/modules/ai/services/circuit-breaker.service.ts
export class CircuitBreakerService {
private failureCount = 0;
private readonly threshold = 5;
private circuitOpen = false;
private readonly resetTimeout = 60000; // 1 minute
async execute<T>(
primaryFn: () => Promise<T>,
fallbackFn: () => Promise<T>,
): Promise<T> {
if (this.circuitOpen) {
return fallbackFn();
}
try {
const result = await primaryFn();
this.failureCount = 0;
return result;
} catch (error) {
this.failureCount++;
if (this.failureCount >= this.threshold) {
this.openCircuit();
}
return fallbackFn();
}
}
private openCircuit() {
this.circuitOpen = true;
setTimeout(() => {
this.circuitOpen = false;
this.failureCount = 0;
}, this.resetTimeout);
}
}
```
## Security Considerations
1. **API Key Rotation**: Store keys in secure vault (AWS Secrets Manager, Azure Key Vault)
2. **Network Security**: Use private endpoints when available
3. **Rate Limiting**: Implement per-user and per-endpoint rate limits
4. **Audit Logging**: Log all AI requests with user context for compliance
## Deployment Checklist
- [ ] Environment variables configured for both OpenAI and Azure
- [ ] API keys validated and working
- [ ] Fallback logic tested in staging
- [ ] Monitoring and alerting configured
- [ ] Rate limiting implemented
- [ ] Circuit breaker tested
- [ ] Error handling covers all failure scenarios
- [ ] Cost tracking enabled
- [ ] Security review completed

View File

@@ -1,320 +0,0 @@
# Azure OpenAI Configuration - Test Results
## ✅ Test Status: ALL SERVICES PASSED
Date: October 1, 2025
Services Tested: Chat (GPT-5-mini), Embeddings (ada-002), Whisper (skipped - requires audio)
---
## Configuration Verified
### Environment Variables - Chat Service
```bash
AI_PROVIDER=azure
AZURE_OPENAI_ENABLED=true
AZURE_OPENAI_CHAT_ENDPOINT=https://footprints-open-ai.openai.azure.com
AZURE_OPENAI_CHAT_DEPLOYMENT=gpt-5-mini
AZURE_OPENAI_CHAT_API_VERSION=2025-04-01-preview
AZURE_OPENAI_CHAT_API_KEY=*** (configured)
AZURE_OPENAI_REASONING_EFFORT=medium
```
### Environment Variables - Embeddings Service
```bash
AZURE_OPENAI_EMBEDDINGS_ENDPOINT=https://footprints-ai.openai.azure.com
AZURE_OPENAI_EMBEDDINGS_DEPLOYMENT=Text-Embedding-ada-002-V2
AZURE_OPENAI_EMBEDDINGS_API_VERSION=2023-05-15
AZURE_OPENAI_EMBEDDINGS_API_KEY=*** (configured)
```
### Environment Variables - Whisper Service
```bash
AZURE_OPENAI_WHISPER_ENDPOINT=https://footprints-open-ai.openai.azure.com
AZURE_OPENAI_WHISPER_DEPLOYMENT=whisper
AZURE_OPENAI_WHISPER_API_VERSION=2025-04-01-preview
AZURE_OPENAI_WHISPER_API_KEY=*** (configured)
```
### API Keys Configured
- ✅ AZURE_OPENAI_CHAT_API_KEY (Chat/GPT-5) - TESTED ✅
- ✅ AZURE_OPENAI_EMBEDDINGS_API_KEY (Text embeddings) - TESTED ✅
- ✅ AZURE_OPENAI_WHISPER_API_KEY (Voice transcription) - CONFIGURED ⏭️
---
## GPT-5 Specific Requirements ⚠️
### Critical Differences from GPT-4
**1. Parameter Name Change:**
```typescript
// ❌ GPT-4 uses max_tokens
max_tokens: 1000 // DOES NOT WORK with GPT-5
// ✅ GPT-5 uses max_completion_tokens
max_completion_tokens: 1000 // CORRECT for GPT-5
```
**2. Temperature Restriction:**
```typescript
// ❌ GPT-4 supports any temperature
temperature: 0.7 // DOES NOT WORK with GPT-5
// ✅ GPT-5 only supports temperature=1 (default)
// SOLUTION: Omit the temperature parameter entirely
```
**3. Reasoning Effort (GPT-5 Only):**
```typescript
// ✅ New GPT-5 parameter
reasoning_effort: 'medium' // Options: 'minimal', 'low', 'medium', 'high'
```
### Updated Request Format
```typescript
const requestBody = {
messages: [
{ role: 'system', content: 'You are a helpful assistant.' },
{ role: 'user', content: 'Hello!' }
],
// temperature: <omitted for GPT-5>
max_completion_tokens: 1000, // Note: NOT max_tokens
reasoning_effort: 'medium',
stream: false
};
```
---
## Test Results
### 1. Chat API (GPT-5-mini) ✅
**Request:**
```json
{
"messages": [
{
"role": "system",
"content": "You are a helpful parenting assistant."
},
{
"role": "user",
"content": "Say 'Hello! Azure OpenAI Chat is working!' if you receive this."
}
],
"max_completion_tokens": 100,
"reasoning_effort": "medium"
}
```
**Response:**
```
Model: gpt-5-mini-2025-08-07
Finish Reason: length
Status: 200 OK
Token Usage:
├── Prompt tokens: 33
├── Completion tokens: 100
├── Reasoning tokens: 0 (GPT-5 feature)
└── Total tokens: 133
```
### 2. Embeddings API (text-embedding-ada-002) ✅
**Request:**
```json
{
"input": "Test embedding for parenting app"
}
```
**Response:**
```
Model: text-embedding-ada-002
Embedding Dimensions: 1536
Status: 200 OK
Token Usage:
├── Prompt tokens: 5
└── Total tokens: 5
```
### 3. Whisper API (Voice Transcription) ⏭️
**Status:** Skipped - Requires audio file upload
Testing Whisper requires a multipart/form-data request with an audio file. This can be tested separately when implementing voice features.
---
## Code Updates Made
### 1. AI Service (`src/modules/ai/ai.service.ts`)
**Changed:**
```typescript
// Before (incorrect for GPT-5)
const requestBody = {
messages: azureMessages,
temperature: 0.7,
max_tokens: maxTokens,
reasoning_effort: this.azureReasoningEffort,
};
// After (correct for GPT-5)
const requestBody = {
messages: azureMessages,
// temperature omitted - GPT-5 only supports default (1)
max_completion_tokens: maxTokens,
reasoning_effort: this.azureReasoningEffort,
stream: false,
};
```
### 2. Test Script (`test-azure-openai.js`)
Created standalone test script with:
- ✅ Environment variable validation
- ✅ API connectivity check
- ✅ GPT-5 specific parameter handling
- ✅ Detailed error reporting
- ✅ Token usage tracking
**Usage:**
```bash
node test-azure-openai.js
```
---
## Migration Guide: GPT-4 → GPT-5
If migrating from GPT-4 to GPT-5, update all Azure OpenAI calls:
### Required Changes
| Aspect | GPT-4 | GPT-5 |
|--------|-------|-------|
| Max tokens parameter | `max_tokens` | `max_completion_tokens` |
| Temperature support | Any value (0-2) | Only 1 (default) |
| Reasoning effort | Not supported | Required parameter |
| API version | `2023-05-15` | `2025-04-01-preview` |
### Code Migration
```typescript
// GPT-4 Request
{
temperature: 0.7, // ❌ Remove
max_tokens: 1000, // ❌ Rename
}
// GPT-5 Request
{
// temperature omitted // ✅ Default to 1
max_completion_tokens: 1000, // ✅ New name
reasoning_effort: 'medium', // ✅ Add this
}
```
---
## Performance Characteristics
### Token Efficiency
- **Reasoning tokens**: 0 (in this test with reasoning_effort='medium')
- **Context window**: 400K tokens (272K input + 128K output)
- **Response quality**: High with reasoning effort
### Cost Implications
- Input: $1.25 / 1M tokens
- Output: $10.00 / 1M tokens
- Cached input: $0.125 / 1M (90% discount)
- Reasoning tokens: Additional cost
---
## Next Steps
### 1. Production Deployment
- ✅ Configuration verified
- ✅ API keys working
- ✅ Code updated for GPT-5
- ⏳ Update documentation
- ⏳ Monitor token usage
- ⏳ Optimize reasoning_effort based on use case
### 2. Recommended Settings
**For Chat (General Questions):**
```bash
AZURE_OPENAI_REASONING_EFFORT=low
AZURE_OPENAI_CHAT_MAX_TOKENS=500
```
**For Complex Analysis:**
```bash
AZURE_OPENAI_REASONING_EFFORT=high
AZURE_OPENAI_CHAT_MAX_TOKENS=2000
```
**For Quick Responses:**
```bash
AZURE_OPENAI_REASONING_EFFORT=minimal
AZURE_OPENAI_CHAT_MAX_TOKENS=200
```
### 3. Monitoring
Track these metrics:
- ✅ API response time
- ✅ Reasoning token usage
- ✅ Total token consumption
- ✅ Error rate
- ✅ Fallback to OpenAI frequency
---
## Troubleshooting
### Common Errors
**Error: "Unsupported parameter: 'max_tokens'"**
- ✅ Solution: Use `max_completion_tokens` instead
**Error: "'temperature' does not support 0.7"**
- ✅ Solution: Remove temperature parameter
**Error: 401 Unauthorized**
- Check: AZURE_OPENAI_CHAT_API_KEY is correct
- Check: API key has access to the deployment
**Error: 404 Not Found**
- Check: AZURE_OPENAI_CHAT_DEPLOYMENT name matches Azure portal
- Check: Deployment exists in the specified endpoint
---
## Summary
**All Azure OpenAI Services are fully configured and working**
Key achievements:
- ✅ Chat API (GPT-5-mini) tested and working
- ✅ Embeddings API (text-embedding-ada-002) tested and working
- ✅ Whisper API (voice transcription) configured (requires audio file to test)
- ✅ Environment variables properly configured for all services
- ✅ API connectivity verified for testable services
- ✅ GPT-5 specific parameters implemented
- ✅ Comprehensive test script created for future validation
- ✅ Code updated in AI service
- ✅ Documentation updated with GPT-5 requirements and all service details
The maternal app is now ready to use all Azure OpenAI services:
- **Chat/Assistant features** using GPT-5-mini
- **Semantic search and similarity** using text-embedding-ada-002
- **Voice input transcription** using Whisper (when implemented)

File diff suppressed because it is too large Load Diff

View File

@@ -1,551 +0,0 @@
# AI Context & Prompting Templates - Maternal Organization App
## LangChain Configuration
### Core Setup
```typescript
// services/ai/langchainConfig.ts
import { ChatOpenAI } from 'langchain/chat_models/openai';
import { ConversationSummaryMemory } from 'langchain/memory';
import { PromptTemplate } from 'langchain/prompts';
import { LLMChain } from 'langchain/chains';
export const initializeLangChain = () => {
const model = new ChatOpenAI({
modelName: 'gpt-4-turbo-preview',
temperature: 0.7,
maxTokens: 1000,
openAIApiKey: process.env.OPENAI_API_KEY,
callbacks: [
{
handleLLMStart: async (llm, prompts) => {
logger.info('LLM request started', { promptLength: prompts[0].length });
},
handleLLMEnd: async (output) => {
logger.info('LLM request completed', { tokensUsed: output.llmOutput?.tokenUsage });
},
},
],
});
const memory = new ConversationSummaryMemory({
memoryKey: 'chat_history',
llm: model,
maxTokenLimit: 2000,
});
return { model, memory };
};
```
### Context Window Management
```typescript
class ContextManager {
private maxContextTokens = 4000;
private priorityWeights = {
currentQuery: 1.0,
recentActivities: 0.8,
childProfile: 0.7,
historicalPatterns: 0.6,
generalGuidelines: 0.4,
};
async buildContext(
query: string,
childId: string,
userId: string
): Promise<AIContext> {
const contexts = await Promise.all([
this.getChildProfile(childId),
this.getRecentActivities(childId, 48), // Last 48 hours
this.getPatterns(childId),
this.getParentPreferences(userId),
this.getPreviousConversation(userId, childId),
]);
return this.prioritizeContext(contexts, query);
}
private prioritizeContext(
contexts: ContextPart[],
query: string
): AIContext {
// Token counting
let currentTokens = this.countTokens(query);
const prioritizedContexts: ContextPart[] = [];
// Sort by relevance and priority
const sorted = contexts
.map(ctx => ({
...ctx,
score: this.calculateRelevance(ctx, query) * this.priorityWeights[ctx.type],
}))
.sort((a, b) => b.score - a.score);
// Add contexts until token limit
for (const context of sorted) {
const tokens = this.countTokens(context.content);
if (currentTokens + tokens <= this.maxContextTokens) {
prioritizedContexts.push(context);
currentTokens += tokens;
}
}
return {
query,
contexts: prioritizedContexts,
totalTokens: currentTokens,
};
}
}
```
---
## System Prompts
### Base System Prompt
```typescript
const BASE_SYSTEM_PROMPT = `You are a knowledgeable, empathetic AI assistant helping parents care for their children aged 0-6 years.
Core Guidelines:
1. SAFETY FIRST: Never provide medical diagnoses. Always recommend consulting healthcare providers for medical concerns.
2. EVIDENCE-BASED: Provide advice based on pediatric best practices and research.
3. PARENT-SUPPORTIVE: Be encouraging and non-judgmental. Every family is different.
4. PRACTICAL: Give actionable, realistic suggestions that work for busy parents.
5. CULTURALLY AWARE: Respect diverse parenting approaches and cultural practices.
You have access to:
- The child's recent activity data (feeding, sleep, diapers)
- Developmental milestones for their age
- Pattern analysis from their historical data
- Family preferences and routines
Response Guidelines:
- Keep responses concise (under 150 words unless asked for detail)
- Use simple, clear language (avoid medical jargon)
- Provide specific, actionable suggestions
- Acknowledge parent concerns with empathy
- Include relevant safety warnings when appropriate`;
```
### Child-Specific Context Template
```typescript
const CHILD_CONTEXT_TEMPLATE = `Child Profile:
- Name: {childName}
- Age: {ageInMonths} months ({ageInYears} years)
- Developmental Stage: {developmentalStage}
- Known Conditions: {medicalConditions}
- Allergies: {allergies}
Recent Patterns (last 7 days):
- Average sleep: {avgSleepHours} hours/day
- Feeding frequency: Every {feedingInterval} hours
- Growth trajectory: {growthPercentile} percentile
Current Concerns:
{parentConcerns}
Recent Activities (last 24 hours):
{recentActivities}`;
```
---
## Prompt Templates by Scenario
### Sleep-Related Queries
```typescript
const SLEEP_PROMPT = PromptTemplate.fromTemplate(`
${BASE_SYSTEM_PROMPT}
Context:
{childContext}
Sleep-Specific Data:
- Recent bedtimes: {recentBedtimes}
- Wake windows today: {wakeWindows}
- Nap schedule: {napSchedule}
- Sleep regression risk: {regressionRisk}
Parent Question: {question}
Provide practical sleep advice considering:
1. Age-appropriate wake windows
2. Recent sleep patterns
3. Common sleep regressions at this age
4. Environmental factors
Response:
`);
```
### Feeding Queries
```typescript
const FEEDING_PROMPT = PromptTemplate.fromTemplate(`
${BASE_SYSTEM_PROMPT}
Context:
{childContext}
Feeding-Specific Data:
- Feeding type: {feedingType}
- Recent intake: {recentIntake}
- Growth trend: {growthTrend}
- Solid foods status: {solidsStatus}
Parent Question: {question}
Provide feeding guidance considering:
1. Age-appropriate feeding amounts
2. Growth patterns
3. Feeding milestones
4. Any mentioned concerns
Response:
`);
```
### Developmental Milestones
```typescript
const MILESTONE_PROMPT = PromptTemplate.fromTemplate(`
${BASE_SYSTEM_PROMPT}
Context:
{childContext}
Developmental Data:
- Expected milestones: {expectedMilestones}
- Achieved milestones: {achievedMilestones}
- Areas of focus: {developmentalFocus}
Parent Question: {question}
Provide developmental guidance:
1. What's typical for this age
2. Activities to encourage development
3. When to consult professionals
4. Celebrate achievements while avoiding comparison
Response:
`);
```
### Behavioral Concerns
```typescript
const BEHAVIOR_PROMPT = PromptTemplate.fromTemplate(`
${BASE_SYSTEM_PROMPT}
Context:
{childContext}
Behavioral Patterns:
- Recent behaviors: {recentBehaviors}
- Triggers identified: {triggers}
- Sleep/hunger status: {physiologicalState}
Parent Question: {question}
Provide behavioral guidance:
1. Age-appropriate expectations
2. Positive parenting strategies
3. Understanding underlying needs
4. Consistency and routine importance
Response:
`);
```
---
## Safety Boundaries
### Medical Disclaimer Triggers
```typescript
const MEDICAL_TRIGGERS = [
'diagnose', 'disease', 'syndrome', 'disorder',
'medication', 'dosage', 'prescription',
'emergency', 'urgent', 'bleeding', 'unconscious',
'seizure', 'fever over 104', 'difficulty breathing',
];
const MEDICAL_DISCLAIMER = `I understand you're concerned about {concern}. This seems like a medical issue that requires professional evaluation. Please contact your pediatrician or healthcare provider immediately. If this is an emergency, call your local emergency number.
For reference, here are signs requiring immediate medical attention:
- Difficulty breathing or bluish skin
- Unresponsiveness or difficulty waking
- High fever (over 104°F/40°C)
- Severe dehydration
- Head injury with vomiting or confusion`;
```
### Mental Health Support
```typescript
const MENTAL_HEALTH_PROMPT = `I hear that you're going through a difficult time. Your feelings are valid and important.
Here are some immediate resources:
- Postpartum Support International: 1-800-4-PPD-MOMS
- Crisis Text Line: Text HOME to 741741
- Local support groups: {localResources}
Please consider reaching out to:
- Your healthcare provider
- A mental health professional
- Trusted family or friends
Remember: Seeking help is a sign of strength, not weakness. Your wellbeing matters for both you and your baby.`;
```
---
## Response Formatting
### Structured Response Template
```typescript
interface AIResponse {
mainAnswer: string;
keyPoints?: string[];
actionItems?: string[];
safetyNotes?: string[];
relatedResources?: Resource[];
confidenceLevel: 'high' | 'medium' | 'low';
shouldEscalate: boolean;
}
const formatResponse = (raw: string, metadata: ResponseMetadata): AIResponse => {
return {
mainAnswer: extractMainAnswer(raw),
keyPoints: extractBulletPoints(raw),
actionItems: extractActionItems(raw),
safetyNotes: extractSafetyWarnings(raw),
relatedResources: findRelevantResources(metadata),
confidenceLevel: calculateConfidence(metadata),
shouldEscalate: checkEscalationTriggers(raw),
};
};
```
### Localized Response Generation
```typescript
const LOCALIZED_PROMPTS = {
'en-US': {
greeting: "I understand your concern about {topic}.",
transition: "Based on {childName}'s patterns,",
closing: "Remember, every baby is different.",
},
'es-ES': {
greeting: "Entiendo tu preocupación sobre {topic}.",
transition: "Basándome en los patrones de {childName},",
closing: "Recuerda, cada bebé es diferente.",
},
'fr-FR': {
greeting: "Je comprends votre inquiétude concernant {topic}.",
transition: "D'après les habitudes de {childName},",
closing: "Rappelez-vous, chaque bébé est unique.",
},
};
```
---
## Personalization Engine
### Learning from Feedback
```typescript
class PersonalizationEngine {
async updateResponsePreferences(
userId: string,
feedback: UserFeedback
) {
const preferences = await this.getUserPreferences(userId);
// Update preference weights
if (feedback.helpful) {
preferences.preferredResponseLength = feedback.responseLength;
preferences.preferredDetailLevel = feedback.detailLevel;
preferences.preferredTone = feedback.tone;
}
// Learn from negative feedback
if (!feedback.helpful && feedback.reason) {
this.adjustPromptTemplate(preferences, feedback.reason);
}
await this.saveUserPreferences(userId, preferences);
}
private adjustPromptTemplate(
preferences: UserPreferences,
reason: string
): PromptTemplate {
const adjustments = {
'too_technical': { jargonLevel: 'minimal', explanationStyle: 'simple' },
'too_general': { specificityLevel: 'high', includeExamples: true },
'too_long': { maxLength: 100, bulletPoints: true },
'not_actionable': { focusOnActions: true, includeSteps: true },
};
return this.applyAdjustments(preferences, adjustments[reason]);
}
}
```
---
## Chain of Thought for Complex Queries
### Multi-Step Reasoning
```typescript
const COMPLEX_REASONING_PROMPT = `Let me analyze this step-by-step:
Step 1: Understanding the Situation
{situationAnalysis}
Step 2: Identifying Patterns
Looking at {childName}'s recent data:
{patternAnalysis}
Step 3: Considering Age-Appropriate Norms
For a {ageInMonths}-month-old:
{developmentalNorms}
Step 4: Practical Recommendations
Based on the above:
{recommendations}
Step 5: What to Monitor
Keep track of:
{monitoringPoints}`;
```
---
## Conversation Memory Management
### Memory Summarization
```typescript
class ConversationMemory {
private maxConversationLength = 10;
async summarizeConversation(
messages: Message[],
childId: string
): Promise<string> {
if (messages.length <= 3) {
return messages.map(m => m.content).join('\n');
}
const summary = await this.llm.summarize({
messages,
focusPoints: [
'Main concerns discussed',
'Advice given',
'Action items suggested',
'Follow-up needed',
],
});
return summary;
}
async getRelevantHistory(
userId: string,
childId: string,
currentQuery: string
): Promise<string> {
const history = await this.fetchHistory(userId, childId);
// Semantic search for relevant past conversations
const relevant = await this.semanticSearch(history, currentQuery);
return this.formatHistory(relevant);
}
}
```
---
## Prompt Injection Protection
### Security Filters
```typescript
const INJECTION_PATTERNS = [
/ignore previous instructions/i,
/system:/i,
/admin mode/i,
/bypass safety/i,
/pretend you are/i,
];
const sanitizeUserInput = (input: string): string => {
// Check for injection attempts
for (const pattern of INJECTION_PATTERNS) {
if (pattern.test(input)) {
logger.warn('Potential prompt injection detected', { input });
return 'Please ask a question about childcare.';
}
}
// Escape special characters
return input
.replace(/[<>]/g, '')
.substring(0, 500); // Limit length
};
```
---
## Testing Prompt Effectiveness
### Prompt Evaluation Metrics
```typescript
interface PromptMetrics {
relevance: number; // 0-1: Response answers the question
safety: number; // 0-1: Appropriate medical disclaimers
actionability: number; // 0-1: Practical suggestions provided
empathy: number; // 0-1: Supportive tone
accuracy: number; // 0-1: Factually correct
}
const evaluatePromptResponse = async (
prompt: string,
response: string,
expectedQualities: PromptMetrics
): Promise<EvaluationResult> => {
const evaluation = await this.evaluatorLLM.evaluate({
prompt,
response,
criteria: expectedQualities,
});
return {
passed: evaluation.overall > 0.8,
metrics: evaluation,
suggestions: evaluation.improvements,
};
};
```
### Test Cases
```typescript
const promptTestCases = [
{
scenario: 'Sleep regression concern',
input: 'My 4-month-old suddenly won\'t sleep',
expectedResponse: {
containsMention: ['4-month sleep regression', 'normal', 'temporary'],
includesActions: ['consistent bedtime', 'wake windows'],
avoidsMedical: true,
},
},
{
scenario: 'Feeding amount worry',
input: 'Is 4oz enough for my 2-month-old?',
expectedResponse: {
containsMention: ['varies by baby', 'weight gain', 'wet diapers'],
includesActions: ['track intake', 'consult pediatrician'],
providesRanges: true,
},
},
];
```

View File

@@ -1,939 +0,0 @@
# API Specification Document - Maternal Organization App
## API Architecture Overview
### Base Configuration
- **Base URL**: `https://api.{domain}/api/v1`
- **GraphQL Endpoint**: `https://api.{domain}/graphql`
- **WebSocket**: `wss://api.{domain}/ws`
- **API Style**: Hybrid (REST for CRUD, GraphQL for complex queries)
- **Versioning**: URL path versioning (`/api/v1/`)
- **Rate Limiting**: 100 requests/minute per user
- **Pagination**: Cursor-based with consistent structure
### Standard Headers
```http
Content-Type: application/json
Accept: application/json
Accept-Language: en-US,en;q=0.9
X-Client-Version: 1.0.0
X-Device-ID: uuid-device-fingerprint
X-Timezone: America/New_York
Authorization: Bearer {access_token}
X-Refresh-Token: {refresh_token}
```
### Device Fingerprinting
```json
{
"deviceId": "uuid",
"platform": "ios|android",
"model": "iPhone14,2",
"osVersion": "16.5",
"appVersion": "1.0.0",
"pushToken": "fcm_or_apns_token"
}
```
---
## Authentication Endpoints
### POST `/api/v1/auth/register`
Create new user account with family setup.
**Request Body:**
```json
{
"email": "user@example.com",
"password": "SecurePass123!",
"phone": "+1234567890",
"name": "Jane Doe",
"locale": "en-US",
"timezone": "America/New_York",
"deviceInfo": {
"deviceId": "uuid",
"platform": "ios",
"model": "iPhone14,2",
"osVersion": "16.5"
}
}
```
**Response 201:**
```json
{
"success": true,
"data": {
"user": {
"id": "usr_2n4k8m9p",
"email": "user@example.com",
"name": "Jane Doe",
"locale": "en-US",
"emailVerified": false
},
"family": {
"id": "fam_7h3j9k2m",
"shareCode": "ABC123",
"role": "parent"
},
"tokens": {
"accessToken": "eyJhbGc...",
"refreshToken": "eyJhbGc...",
"expiresIn": 3600
},
"deviceRegistered": true
}
}
```
### POST `/api/v1/auth/login`
Authenticate existing user with device registration.
**Request Body:**
```json
{
"email": "user@example.com",
"password": "SecurePass123!",
"deviceInfo": {
"deviceId": "uuid",
"platform": "ios",
"model": "iPhone14,2",
"osVersion": "16.5"
}
}
```
**Response 200:**
```json
{
"success": true,
"data": {
"user": {
"id": "usr_2n4k8m9p",
"email": "user@example.com",
"families": ["fam_7h3j9k2m"]
},
"tokens": {
"accessToken": "eyJhbGc...",
"refreshToken": "eyJhbGc...",
"expiresIn": 3600
},
"requiresMFA": false,
"deviceTrusted": true
}
}
```
### POST `/api/v1/auth/refresh`
Refresh access token using refresh token.
**Request Body:**
```json
{
"refreshToken": "eyJhbGc...",
"deviceId": "uuid"
}
```
**Response 200:**
```json
{
"success": true,
"data": {
"accessToken": "eyJhbGc...",
"refreshToken": "eyJhbGc...",
"expiresIn": 3600
}
}
```
### POST `/api/v1/auth/logout`
Logout and revoke tokens for specific device.
**Request Body:**
```json
{
"deviceId": "uuid",
"allDevices": false
}
```
**Response 200:**
```json
{
"success": true,
"message": "Successfully logged out"
}
```
---
## Family Management Endpoints
### POST `/api/v1/families/invite`
Generate invitation for family member.
**Request Body:**
```json
{
"email": "partner@example.com",
"role": "parent|caregiver|viewer",
"permissions": {
"canAddChildren": true,
"canEditChildren": true,
"canLogActivities": true,
"canViewReports": true
},
"message": "Join our family on the app!"
}
```
**Response 201:**
```json
{
"success": true,
"data": {
"invitationId": "inv_8k3m9n2p",
"shareCode": "XYZ789",
"expiresAt": "2024-01-15T00:00:00Z",
"invitationUrl": "app://join/XYZ789"
}
}
```
### POST `/api/v1/families/join`
Join family using share code.
**Request Body:**
```json
{
"shareCode": "XYZ789"
}
```
**Response 200:**
```json
{
"success": true,
"data": {
"familyId": "fam_7h3j9k2m",
"familyName": "The Doe Family",
"role": "parent",
"members": [
{
"id": "usr_2n4k8m9p",
"name": "Jane Doe",
"role": "parent"
}
],
"children": []
}
}
```
### GET `/api/v1/families/{familyId}/members`
Get all family members with their permissions.
**Response 200:**
```json
{
"success": true,
"data": {
"members": [
{
"id": "usr_2n4k8m9p",
"name": "Jane Doe",
"email": "jane@example.com",
"role": "parent",
"permissions": {
"canAddChildren": true,
"canEditChildren": true,
"canLogActivities": true,
"canViewReports": true
},
"joinedAt": "2024-01-01T00:00:00Z",
"lastActive": "2024-01-10T15:30:00Z"
}
]
}
}
```
---
## Children Management Endpoints
### POST `/api/v1/children`
Add a new child to the family.
**Request Body:**
```json
{
"familyId": "fam_7h3j9k2m",
"name": "Emma",
"birthDate": "2023-06-15",
"gender": "female",
"bloodType": "O+",
"allergies": ["peanuts", "dairy"],
"medicalConditions": ["eczema"],
"pediatrician": {
"name": "Dr. Smith",
"phone": "+1234567890"
},
"photo": "base64_encoded_image"
}
```
**Response 201:**
```json
{
"success": true,
"data": {
"id": "chd_9m2k4n8p",
"familyId": "fam_7h3j9k2m",
"name": "Emma",
"birthDate": "2023-06-15",
"ageInMonths": 7,
"developmentalStage": "infant",
"photoUrl": "https://storage.api/photos/chd_9m2k4n8p.jpg"
}
}
```
### GET `/api/v1/children/{childId}`
Get child details with calculated metrics.
**Response 200:**
```json
{
"success": true,
"data": {
"id": "chd_9m2k4n8p",
"name": "Emma",
"birthDate": "2023-06-15",
"ageInMonths": 7,
"developmentalStage": "infant",
"currentWeight": {
"value": 8.2,
"unit": "kg",
"percentile": 75,
"recordedAt": "2024-01-10T10:00:00Z"
},
"currentHeight": {
"value": 68,
"unit": "cm",
"percentile": 80,
"recordedAt": "2024-01-10T10:00:00Z"
},
"todaySummary": {
"feedings": 5,
"sleepHours": 14.5,
"diapers": 6,
"lastFeedingAt": "2024-01-10T14:30:00Z",
"lastSleepAt": "2024-01-10T13:00:00Z"
}
}
}
```
---
## Activity Tracking Endpoints (REST)
### POST `/api/v1/activities/feeding`
Log a feeding activity.
**Request Body:**
```json
{
"childId": "chd_9m2k4n8p",
"type": "breast|bottle|solid",
"startTime": "2024-01-10T14:30:00Z",
"endTime": "2024-01-10T14:45:00Z",
"details": {
"breastSide": "left|right|both",
"amount": 120,
"unit": "ml|oz",
"foodType": "formula|breastmilk|puree"
},
"notes": "Good feeding session",
"mood": "happy|fussy|sleepy"
}
```
**Response 201:**
```json
{
"success": true,
"data": {
"id": "act_3k9n2m4p",
"childId": "chd_9m2k4n8p",
"type": "feeding",
"timestamp": "2024-01-10T14:30:00Z",
"duration": 15,
"createdBy": "usr_2n4k8m9p",
"syncedToFamily": true
}
}
```
### POST `/api/v1/activities/sleep`
Log sleep activity.
**Request Body:**
```json
{
"childId": "chd_9m2k4n8p",
"startTime": "2024-01-10T13:00:00Z",
"endTime": "2024-01-10T14:30:00Z",
"type": "nap|night",
"location": "crib|stroller|car|bed",
"quality": "good|restless|interrupted",
"notes": "Went down easily"
}
```
### POST `/api/v1/activities/diaper`
Log diaper change.
**Request Body:**
```json
{
"childId": "chd_9m2k4n8p",
"timestamp": "2024-01-10T15:00:00Z",
"type": "wet|dirty|both",
"consistency": "normal|loose|hard",
"color": "normal|green|yellow",
"hasRash": false,
"notes": "Applied diaper cream"
}
```
### GET `/api/v1/activities`
Get activities with cursor pagination.
**Query Parameters:**
- `childId`: Filter by child (required)
- `type`: Filter by activity type
- `startDate`: ISO date string
- `endDate`: ISO date string
- `cursor`: Pagination cursor
- `limit`: Items per page (default: 20, max: 100)
**Response 200:**
```json
{
"success": true,
"data": {
"activities": [
{
"id": "act_3k9n2m4p",
"childId": "chd_9m2k4n8p",
"type": "feeding",
"timestamp": "2024-01-10T14:30:00Z",
"details": {},
"createdBy": "usr_2n4k8m9p"
}
],
"cursor": {
"next": "eyJpZCI6ImFjdF8za...",
"hasMore": true,
"total": 150
}
}
}
```
---
## AI Assistant Endpoints
### POST `/api/v1/ai/chat`
Send message to AI assistant.
**Request Body:**
```json
{
"message": "Why won't my baby sleep?",
"childId": "chd_9m2k4n8p",
"conversationId": "conv_8n2k4m9p",
"context": {
"includeRecentActivities": true,
"includeSleepPatterns": true,
"includeDevelopmentalInfo": true
},
"locale": "en-US"
}
```
**Response 200:**
```json
{
"success": true,
"data": {
"conversationId": "conv_8n2k4m9p",
"messageId": "msg_7k3n9m2p",
"response": "Based on Emma's recent sleep patterns...",
"suggestions": [
"Try starting bedtime routine 15 minutes earlier",
"Check room temperature (ideal: 68-72°F)"
],
"relatedArticles": [
{
"title": "7-Month Sleep Regression",
"url": "/resources/sleep-regression-7-months"
}
],
"confidenceScore": 0.92
}
}
```
### POST `/api/v1/ai/voice`
Process voice command.
**Request Body (multipart/form-data):**
```
audio: [audio file - wav/mp3]
childId: chd_9m2k4n8p
locale: en-US
```
**Response 200:**
```json
{
"success": true,
"data": {
"transcription": "Baby fed 4 ounces at 3pm",
"interpretation": {
"action": "log_feeding",
"childId": "chd_9m2k4n8p",
"parameters": {
"amount": 4,
"unit": "oz",
"time": "15:00"
}
},
"executed": true,
"activityId": "act_9k2m4n3p"
}
}
```
---
## Analytics & Insights Endpoints
### GET `/api/v1/insights/{childId}/patterns`
Get AI-detected patterns for a child.
**Response 200:**
```json
{
"success": true,
"data": {
"sleepPatterns": {
"averageNightSleep": 10.5,
"averageDaySleep": 3.5,
"optimalBedtime": "19:30",
"wakeWindows": [90, 120, 150, 180],
"trend": "improving",
"insights": [
"Emma sleeps 45 minutes longer when put down before 7:30 PM",
"Morning wake time is consistently between 6:30-7:00 AM"
]
},
"feedingPatterns": {
"averageIntake": 28,
"feedingIntervals": [2.5, 3, 3, 4],
"preferredSide": "left",
"insights": [
"Feeding intervals increasing - may be ready for longer stretches"
]
}
}
}
```
### GET `/api/v1/insights/{childId}/predictions`
Get predictive suggestions.
**Response 200:**
```json
{
"success": true,
"data": {
"nextNapTime": {
"predicted": "2024-01-10T16:30:00Z",
"confidence": 0.85,
"wakeWindow": 120
},
"nextFeedingTime": {
"predicted": "2024-01-10T17:30:00Z",
"confidence": 0.78
},
"growthSpurt": {
"likelihood": 0.72,
"expectedIn": "5-7 days",
"symptoms": ["increased feeding", "fussiness", "disrupted sleep"]
}
}
}
```
---
## GraphQL Queries for Complex Data
### GraphQL Endpoint
`POST https://api.{domain}/graphql`
### Family Dashboard Query
```graphql
query FamilyDashboard($familyId: ID!, $date: Date!) {
family(id: $familyId) {
id
name
children {
id
name
age
todaySummary(date: $date) {
feedings {
count
totalAmount
lastAt
}
sleep {
totalHours
naps
nightSleep
currentStatus
}
diapers {
count
lastAt
}
}
upcomingEvents {
type
scheduledFor
description
}
aiInsights {
message
priority
actionable
}
}
members {
id
name
lastActive
recentActivities(limit: 5) {
type
childName
timestamp
}
}
}
}
```
### Weekly Report Query
```graphql
query WeeklyReport($childId: ID!, $startDate: Date!, $endDate: Date!) {
child(id: $childId) {
weeklyReport(startDate: $startDate, endDate: $endDate) {
sleep {
dailyAverages {
date
nightHours
napHours
totalHours
}
patterns {
consistentBedtime
averageWakeTime
longestStretch
}
}
feeding {
dailyTotals {
date
numberOfFeedings
totalVolume
}
trends {
direction
averageInterval
}
}
growth {
measurements {
date
weight
height
percentiles
}
}
milestones {
achieved {
name
achievedAt
}
upcoming {
name
expectedBy
}
}
}
}
}
```
---
## WebSocket Events
### Connection
```javascript
// Client connects with auth
ws.connect('wss://api.{domain}/ws', {
headers: {
'Authorization': 'Bearer {access_token}',
'X-Device-ID': 'uuid'
}
});
```
### Family Room Events
```javascript
// Join family room
ws.emit('join-family', { familyId: 'fam_7h3j9k2m' });
// Activity logged by family member
ws.on('activity-logged', {
activityId: 'act_3k9n2m4p',
childId: 'chd_9m2k4n8p',
type: 'feeding',
loggedBy: 'usr_2n4k8m9p',
timestamp: '2024-01-10T14:30:00Z'
});
// Real-time timer sync
ws.on('timer-started', {
timerId: 'tmr_8k3m9n2p',
type: 'feeding',
childId: 'chd_9m2k4n8p',
startedBy: 'usr_2n4k8m9p',
startTime: '2024-01-10T14:30:00Z'
});
// AI insight generated
ws.on('insight-available', {
childId: 'chd_9m2k4n8p',
type: 'pattern_detected',
message: 'New sleep pattern identified',
priority: 'medium'
});
```
---
## Error Responses
### Standard Error Format
```json
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid input data",
"details": {
"field": "email",
"reason": "Invalid email format"
},
"timestamp": "2024-01-10T15:30:00Z",
"traceId": "trace_8k3m9n2p"
}
}
```
### Error Codes
| Code | HTTP Status | Description |
|------|------------|-------------|
| `UNAUTHORIZED` | 401 | Invalid or expired token |
| `FORBIDDEN` | 403 | Insufficient permissions |
| `NOT_FOUND` | 404 | Resource not found |
| `VALIDATION_ERROR` | 400 | Invalid input data |
| `RATE_LIMITED` | 429 | Too many requests |
| `FAMILY_FULL` | 400 | Family member limit reached |
| `CHILD_LIMIT` | 400 | Free tier child limit reached |
| `AI_QUOTA_EXCEEDED` | 429 | AI query limit reached |
| `SYNC_CONFLICT` | 409 | Data sync conflict |
| `SERVER_ERROR` | 500 | Internal server error |
### Rate Limit Headers
```http
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1704903000
Retry-After: 3600
```
---
## Localization
### Supported Locales
- `en-US` - English (United States)
- `es-ES` - Spanish (Spain)
- `es-MX` - Spanish (Mexico)
- `fr-FR` - French (France)
- `fr-CA` - French (Canada)
- `pt-BR` - Portuguese (Brazil)
- `zh-CN` - Chinese (Simplified)
### Locale-Specific Responses
All error messages, AI responses, and notifications are returned in the user's selected locale based on the `Accept-Language` header or user profile setting.
### Date/Time Formatting
Dates are returned in ISO 8601 format but should be displayed according to user's locale:
- US: MM/DD/YYYY, 12-hour clock
- EU: DD/MM/YYYY, 24-hour clock
- Time zones always included in responses
### Measurement Units
```json
{
"measurement": {
"value": 8.2,
"unit": "kg",
"display": "8.2 kg",
"imperial": {
"value": 18.08,
"unit": "lbs",
"display": "18 lbs 1 oz"
}
}
}
```
---
## Security Considerations
### Authentication Flow
1. User provides credentials + device fingerprint
2. Server validates and issues access token (1 hour) + refresh token (30 days)
3. Device fingerprint stored and validated on each request
4. Refresh token rotation on use
5. All tokens revoked on suspicious activity
### Data Encryption
- All API communication over HTTPS/TLS 1.3
- Sensitive fields encrypted at rest (AES-256)
- PII data anonymized in logs
- No sensitive data in URL parameters
### COPPA/GDPR Compliance
- Parental consent required for child profiles
- Data minimization enforced
- Right to deletion implemented
- Data portability via export endpoints
- Audit logs for all data access
### Request Signing (Optional Enhanced Security)
```http
X-Signature: HMAC-SHA256(request-body + timestamp + nonce)
X-Timestamp: 1704903000
X-Nonce: unique-request-id
```
---
## Testing Endpoints
### Health Check
`GET /api/v1/health`
**Response 200:**
```json
{
"status": "healthy",
"version": "1.0.0",
"timestamp": "2024-01-10T15:30:00Z",
"services": {
"database": "connected",
"redis": "connected",
"ai": "operational"
}
}
```
### Test Notifications
`POST /api/v1/test/notification`
**Request Body:**
```json
{
"type": "test",
"deviceId": "uuid"
}
```
---
## SDK Usage Examples
### JavaScript/TypeScript
```typescript
import { MaternalAPI } from '@maternal/sdk';
const api = new MaternalAPI({
baseUrl: 'https://api.maternal.app',
version: 'v1'
});
// Authentication
const { tokens, user } = await api.auth.login({
email: 'user@example.com',
password: 'password',
deviceInfo: getDeviceInfo()
});
// Set tokens for subsequent requests
api.setTokens(tokens);
// Log activity
const activity = await api.activities.logFeeding({
childId: 'chd_9m2k4n8p',
type: 'bottle',
amount: 120,
unit: 'ml'
});
// Subscribe to real-time updates
api.websocket.on('activity-logged', (data) => {
console.log('New activity:', data);
});
```
### React Native
```typescript
import { useMaternalAPI } from '@maternal/react-native';
function FeedingScreen() {
const { logFeeding, isLoading } = useMaternalAPI();
const handleLogFeeding = async () => {
await logFeeding({
childId: currentChild.id,
type: 'breast',
duration: 15
});
};
}
```

View File

@@ -1,207 +0,0 @@
================================================================================
MATERNAL APP MVP - DATA FLOW ARCHITECTURE
================================================================================
┌─────────────────────────────────────────────────────────────────────────────┐
│ USER INTERFACE LAYER │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Parent 1 │ │ Parent 2 │ │ Caregiver │ │ Voice Input │ │
│ │ (Mobile) │ │ (Mobile) │ │ (Mobile) │ │ (Whisper) │ │
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
│ │ │ │ │ │
│ └──────────────────┴──────────────────┴──────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────┐ │
│ │ API Gateway (REST) │ │
│ │ Authentication │ │
│ │ Rate Limiting │ │
│ │ i18n Routing │ │
│ └───────────┬───────────┘ │
│ │ │
└──────────────────────────────────────┼──────────────────────────────────────┘
================================================================================
REAL-TIME SYNC LAYER
================================================================================
┌────────────▼────────────┐
│ WebSocket Server │
│ (Socket.io) │
│ ┌──────────────────┐ │
│ │ Event Publisher │ │
│ └──────────────────┘ │
│ ┌──────────────────┐ │
│ │ Family Rooms │ │
│ └──────────────────┘ │
└────────────┬────────────┘
┌─────────────────┼─────────────────┐
│ │ │
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Redis │ │ Redis │ │ Redis │
│ Channel 1│ │ Channel 2│ │ Channel 3│
│ (Family) │ │ (Family) │ │ (Family) │
└──────────┘ └──────────┘ └──────────┘
│ │ │
└─────────────────┼─────────────────┘
================================================================================
APPLICATION SERVICE LAYER
================================================================================
┌──────────────────────────────┼──────────────────────────────┐
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Tracking │ │ AI Assistant │ │ Analytics │
│ Service │ │ Service │ │ Service │
│ │ │ │ │ │
│ • Feeding │ │ • Chat Handler │ │ • Pattern │
│ • Sleep │ │ • Context Mgr │ │ Detection │
│ • Diaper │◄─────────┤ • LLM Gateway │◄─────────┤ • Predictions │
│ • Growth │ │ • Response Gen │ │ • Insights │
│ • Voice Process │ │ │ │ • Reports │
└────────┬────────┘ └────────┬────────┘ └────────┬────────┘
│ │ │
│ ▼ │
│ ┌───────────────────────┐ │
│ │ LLM API Gateway │ │
│ │ ┌────────────────┐ │ │
│ │ │ OpenAI/Claude │ │ │
│ │ └────────────────┘ │ │
│ │ ┌────────────────┐ │ │
│ │ │ Context Cache │ │ │
│ │ └────────────────┘ │ │
│ └───────────────────────┘ │
│ │
└──────────────────────┬──────────────────────────────────┘
================================================================================
DATA PERSISTENCE LAYER
================================================================================
┌───────────▼───────────┐
│ Database Router │
└───────────┬───────────┘
┌───────────────────────┼───────────────────────┐
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ PostgreSQL │ │ MongoDB │ │ Redis │
│ (Primary) │ │ (Documents) │ │ (Cache) │
├──────────────┤ ├──────────────┤ ├──────────────┤
│ • Users │ │ • AI Chats │ │ • Sessions │
│ • Children │ │ • Reports │ │ • Real-time │
│ • Activities │ │ • Analytics │ │ • Predictions│
│ • Families │ │ • Logs │ │ • Temp Data │
│ • Settings │ │ │ │ │
└──────┬───────┘ └──────┬───────┘ └──────┬───────┘
│ │ │
└──────────────────────┼───────────────────────┘
================================================================================
BACKGROUND JOBS LAYER
================================================================================
┌─────────▼─────────┐
│ Message Queue │
│ (Bull) │
└─────────┬─────────┘
┌─────────────────────┼─────────────────────┐
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Notification │ │ ML/AI │ │ Data │
│ Worker │ │ Worker │ │ Export │
├──────────────┤ ├──────────────┤ ├──────────────┤
│ • Push │ │ • Training │ │ • PDF Gen │
│ • Email │ │ • Prediction │ │ • CSV Export │
│ • SMS │ │ • Analysis │ │ • Backup │
└──────────────┘ └──────────────┘ └──────────────┘
================================================================================
DATA FLOW PATTERNS
================================================================================
1. ACTIVITY LOGGING FLOW:
User → Mobile App → API Gateway → Tracking Service → PostgreSQL
WebSocket Server → Redis Pub/Sub → All Family Devices
2. AI ASSISTANT FLOW:
User Query → Voice/Text Input → AI Service → Context Fetch (PostgreSQL)
LLM API → Response Generation
MongoDB (Chat History) → User
3. PATTERN RECOGNITION FLOW:
PostgreSQL Data → Analytics Service → ML Worker → Pattern Detection
Redis Cache → Predictions
Push Notification
4. REAL-TIME SYNC FLOW:
Device A → WebSocket → Redis Channel → WebSocket → Device B
PostgreSQL (Persistence)
5. OFFLINE SYNC FLOW:
Mobile SQLite → Queue Actions → Network Available → Sync Service
PostgreSQL
Conflict Resolution
Update All Devices
================================================================================
SECURITY BOUNDARIES
================================================================================
┌─────────────────────────────────────────────────────────────────────────┐
│ ENCRYPTED AT REST │
│ ┌───────────────────────────────────────────────────────────────────┐ │
│ │ END-TO-END ENCRYPTED │ │
│ │ ┌─────────────────────────────────────────────────────────────┐ │ │
│ │ │ SENSITIVE USER DATA │ │ │
│ │ │ • Child Health Records │ │ │
│ │ │ • Personal Identifiable Information │ │ │
│ │ │ • Location Data │ │ │
│ │ └─────────────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ ENCRYPTED IN TRANSIT │ │
│ └───────────────────────────────────────────────────────────────────┘ │
│ │
│ AUDIT LOGGING │
└─────────────────────────────────────────────────────────────────────────┘
================================================================================
SCALABILITY NOTES
================================================================================
• Horizontal Scaling Points:
- API Gateway (Load Balancer)
- WebSocket Servers (Sticky Sessions)
- Service Layer (Kubernetes Pods)
- Redis (Cluster Mode)
- PostgreSQL (Read Replicas)
• Bottleneck Mitigation:
- LLM API: Response caching, rate limiting
- Database: Connection pooling, query optimization
- Real-time: Redis pub/sub for fan-out
- Storage: CDN for static assets
• Performance Targets:
- API Response: <200ms (p95)
- Real-time Sync: <100ms
- AI Response: <3s
- Offline Support: 7 days of data

View File

@@ -1,412 +0,0 @@
# Database Migration Scripts - Maternal Organization App
## Migration Strategy
### Naming Convention
- Format: `V{version}_{timestamp}_{description}.sql`
- Example: `V001_20240110120000_create_users_table.sql`
- Rollback: `R001_20240110120000_create_users_table.sql`
### Execution Order
Migrations must run sequentially. Each migration is recorded in a `schema_migrations` table to prevent re-execution.
---
## Migration V001: Core Authentication Tables
### Up Migration
```sql
-- V001_20240110120000_create_core_auth.sql
CREATE TABLE users (
id VARCHAR(20) PRIMARY KEY DEFAULT ('usr_' || nanoid()),
email VARCHAR(255) UNIQUE NOT NULL,
phone VARCHAR(20),
password_hash VARCHAR(255) NOT NULL,
name VARCHAR(100) NOT NULL,
locale VARCHAR(10) DEFAULT 'en-US',
timezone VARCHAR(50) DEFAULT 'UTC',
email_verified BOOLEAN DEFAULT FALSE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE device_registry (
id VARCHAR(20) PRIMARY KEY DEFAULT ('dev_' || nanoid()),
user_id VARCHAR(20) NOT NULL REFERENCES users(id) ON DELETE CASCADE,
device_fingerprint VARCHAR(255) NOT NULL,
platform VARCHAR(20) NOT NULL,
trusted BOOLEAN DEFAULT FALSE,
last_seen TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE(user_id, device_fingerprint)
);
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_devices_user ON device_registry(user_id);
```
### Down Migration
```sql
-- R001_20240110120000_create_core_auth.sql
DROP TABLE device_registry;
DROP TABLE users;
```
---
## Migration V002: Family Structure
### Up Migration
```sql
-- V002_20240110130000_create_family_structure.sql
CREATE TABLE families (
id VARCHAR(20) PRIMARY KEY DEFAULT ('fam_' || nanoid()),
name VARCHAR(100),
share_code VARCHAR(10) UNIQUE DEFAULT upper(substr(md5(random()::text), 1, 6)),
created_by VARCHAR(20) REFERENCES users(id),
subscription_tier VARCHAR(20) DEFAULT 'free',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE family_members (
user_id VARCHAR(20) REFERENCES users(id) ON DELETE CASCADE,
family_id VARCHAR(20) REFERENCES families(id) ON DELETE CASCADE,
role VARCHAR(20) NOT NULL CHECK (role IN ('parent', 'caregiver', 'viewer')),
permissions JSONB DEFAULT '{"canAddChildren": false, "canEditChildren": false, "canLogActivities": true, "canViewReports": true}'::jsonb,
joined_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (user_id, family_id)
);
CREATE TABLE children (
id VARCHAR(20) PRIMARY KEY DEFAULT ('chd_' || nanoid()),
family_id VARCHAR(20) NOT NULL REFERENCES families(id) ON DELETE CASCADE,
name VARCHAR(100) NOT NULL,
birth_date DATE NOT NULL,
gender VARCHAR(20),
photo_url TEXT,
medical_info JSONB DEFAULT '{}'::jsonb,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP
);
CREATE INDEX idx_families_share_code ON families(share_code);
CREATE INDEX idx_family_members_family ON family_members(family_id);
CREATE INDEX idx_children_family ON children(family_id);
CREATE INDEX idx_children_active ON children(deleted_at) WHERE deleted_at IS NULL;
```
---
## Migration V003: Activity Tracking Tables
### Up Migration
```sql
-- V003_20240110140000_create_activity_tracking.sql
CREATE TABLE activities (
id VARCHAR(20) PRIMARY KEY DEFAULT ('act_' || nanoid()),
child_id VARCHAR(20) NOT NULL REFERENCES children(id) ON DELETE CASCADE,
type VARCHAR(20) NOT NULL CHECK (type IN ('feeding', 'sleep', 'diaper', 'growth', 'medication', 'temperature')),
started_at TIMESTAMP NOT NULL,
ended_at TIMESTAMP,
logged_by VARCHAR(20) NOT NULL REFERENCES users(id),
notes TEXT,
metadata JSONB DEFAULT '{}'::jsonb,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Partitioned by month for scalability
CREATE TABLE activities_2024_01 PARTITION OF activities
FOR VALUES FROM ('2024-01-01') TO ('2024-02-01');
CREATE INDEX idx_activities_child_time ON activities(child_id, started_at DESC);
CREATE INDEX idx_activities_type ON activities(type, started_at DESC);
CREATE INDEX idx_activities_metadata ON activities USING gin(metadata);
```
---
## Migration V004: AI and Analytics Tables
### Up Migration
```sql
-- V004_20240110150000_create_ai_analytics.sql
CREATE TABLE conversations (
id VARCHAR(20) PRIMARY KEY DEFAULT ('conv_' || nanoid()),
user_id VARCHAR(20) NOT NULL REFERENCES users(id) ON DELETE CASCADE,
child_id VARCHAR(20) REFERENCES children(id) ON DELETE CASCADE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_message_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE messages (
id VARCHAR(20) PRIMARY KEY DEFAULT ('msg_' || nanoid()),
conversation_id VARCHAR(20) NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
role VARCHAR(20) NOT NULL CHECK (role IN ('user', 'assistant')),
content TEXT NOT NULL,
metadata JSONB DEFAULT '{}'::jsonb,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE patterns (
id VARCHAR(20) PRIMARY KEY DEFAULT ('pat_' || nanoid()),
child_id VARCHAR(20) NOT NULL REFERENCES children(id) ON DELETE CASCADE,
type VARCHAR(50) NOT NULL,
pattern_data JSONB NOT NULL,
confidence DECIMAL(3,2),
detected_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
expires_at TIMESTAMP
);
CREATE TABLE predictions (
id VARCHAR(20) PRIMARY KEY DEFAULT ('prd_' || nanoid()),
child_id VARCHAR(20) NOT NULL REFERENCES children(id) ON DELETE CASCADE,
type VARCHAR(50) NOT NULL,
predicted_time TIMESTAMP NOT NULL,
confidence DECIMAL(3,2),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
outcome VARCHAR(20) -- 'correct', 'incorrect', 'pending'
);
CREATE INDEX idx_conversations_user ON conversations(user_id);
CREATE INDEX idx_messages_conversation ON messages(conversation_id);
CREATE INDEX idx_patterns_child_type ON patterns(child_id, type);
CREATE INDEX idx_predictions_child_time ON predictions(child_id, predicted_time);
```
---
## Migration V005: Performance Optimization Indexes
### Up Migration
```sql
-- V005_20240110160000_add_performance_indexes.sql
-- Composite indexes for common queries
CREATE INDEX idx_activities_daily_summary
ON activities(child_id, type, started_at)
WHERE ended_at IS NOT NULL;
CREATE INDEX idx_patterns_active
ON patterns(child_id, type, confidence)
WHERE expires_at > CURRENT_TIMESTAMP;
-- Text search for notes
CREATE INDEX idx_activities_notes_search
ON activities USING gin(to_tsvector('english', notes));
-- Covering index for dashboard query
CREATE INDEX idx_children_dashboard
ON children(family_id, id, name, birth_date)
WHERE deleted_at IS NULL;
```
---
## Migration V006: Notification System
### Up Migration
```sql
-- V006_20240110170000_create_notifications.sql
CREATE TABLE notification_preferences (
user_id VARCHAR(20) PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE,
push_enabled BOOLEAN DEFAULT true,
email_enabled BOOLEAN DEFAULT true,
quiet_hours_start TIME,
quiet_hours_end TIME,
preferences JSONB DEFAULT '{}'::jsonb
);
CREATE TABLE scheduled_notifications (
id VARCHAR(20) PRIMARY KEY DEFAULT ('ntf_' || nanoid()),
user_id VARCHAR(20) NOT NULL REFERENCES users(id) ON DELETE CASCADE,
child_id VARCHAR(20) REFERENCES children(id) ON DELETE CASCADE,
type VARCHAR(50) NOT NULL,
scheduled_for TIMESTAMP NOT NULL,
payload JSONB NOT NULL,
sent_at TIMESTAMP,
status VARCHAR(20) DEFAULT 'pending'
);
CREATE INDEX idx_notifications_pending
ON scheduled_notifications(scheduled_for, status)
WHERE status = 'pending';
```
---
## Migration V007: Audit and Compliance
### Up Migration
```sql
-- V007_20240110180000_create_audit_compliance.sql
CREATE TABLE audit_log (
id BIGSERIAL PRIMARY KEY,
user_id VARCHAR(20),
action VARCHAR(50) NOT NULL,
entity_type VARCHAR(50),
entity_id VARCHAR(20),
changes JSONB,
ip_address INET,
user_agent TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE data_deletion_requests (
id VARCHAR(20) PRIMARY KEY DEFAULT ('del_' || nanoid()),
user_id VARCHAR(20) NOT NULL REFERENCES users(id),
requested_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
scheduled_for TIMESTAMP NOT NULL DEFAULT (CURRENT_TIMESTAMP + INTERVAL '30 days'),
completed_at TIMESTAMP,
status VARCHAR(20) DEFAULT 'pending'
);
-- Partition audit_log by month for retention management
CREATE TABLE audit_log_2024_01 PARTITION OF audit_log
FOR VALUES FROM ('2024-01-01') TO ('2024-02-01');
CREATE INDEX idx_audit_user_action ON audit_log(user_id, action, created_at DESC);
```
---
## Seed Data Script
```sql
-- seed_development_data.sql
-- Test users
INSERT INTO users (id, email, password_hash, name, locale) VALUES
('usr_test1', 'test1@example.com', '$2b$10$...', 'Test Parent 1', 'en-US'),
('usr_test2', 'test2@example.com', '$2b$10$...', 'Test Parent 2', 'es-ES');
-- Test family
INSERT INTO families (id, name, created_by, share_code) VALUES
('fam_test', 'Test Family', 'usr_test1', 'TEST01');
-- Family members
INSERT INTO family_members (user_id, family_id, role, permissions) VALUES
('usr_test1', 'fam_test', 'parent', '{"canAddChildren": true, "canEditChildren": true, "canLogActivities": true, "canViewReports": true}'::jsonb),
('usr_test2', 'fam_test', 'parent', '{"canAddChildren": true, "canEditChildren": true, "canLogActivities": true, "canViewReports": true}'::jsonb);
-- Test children
INSERT INTO children (id, family_id, name, birth_date, gender) VALUES
('chd_test1', 'fam_test', 'Emma', '2023-06-15', 'female'),
('chd_test2', 'fam_test', 'Liam', '2021-03-22', 'male');
```
---
## Migration Runner Configuration
### TypeORM Configuration
```typescript
// ormconfig.ts
export default {
type: 'postgres',
host: process.env.DB_HOST,
port: 5432,
database: process.env.DB_NAME,
migrations: ['src/migrations/*.sql'],
cli: {
migrationsDir: 'src/migrations'
}
};
```
### Knex Configuration
```javascript
// knexfile.js
module.exports = {
development: {
client: 'postgresql',
connection: process.env.DATABASE_URL,
migrations: {
directory: './migrations',
tableName: 'schema_migrations'
}
}
};
```
---
## Database Maintenance Scripts
### Weekly Vacuum
```sql
-- maintenance/weekly_vacuum.sql
VACUUM ANALYZE activities;
VACUUM ANALYZE patterns;
VACUUM ANALYZE predictions;
```
### Monthly Partition Creation
```sql
-- maintenance/create_next_month_partition.sql
CREATE TABLE IF NOT EXISTS activities_2024_02
PARTITION OF activities
FOR VALUES FROM ('2024-02-01') TO ('2024-03-01');
```
### Archive Old Data
```sql
-- maintenance/archive_old_activities.sql
INSERT INTO activities_archive
SELECT * FROM activities
WHERE started_at < CURRENT_DATE - INTERVAL '1 year';
DELETE FROM activities
WHERE started_at < CURRENT_DATE - INTERVAL '1 year';
```
---
## Rollback Procedures
### Full Rollback Script
```bash
#!/bin/bash
# rollback.sh
VERSION=$1
psql $DATABASE_URL -f "migrations/rollback/R${VERSION}.sql"
DELETE FROM schema_migrations WHERE version = $VERSION;
```
### Emergency Recovery
```sql
-- emergency_recovery.sql
-- Point-in-time recovery to specific timestamp
SELECT pg_restore_point('before_migration');
-- Restore from backup if catastrophic failure
```
---
## Performance Considerations
### Index Strategy
- Primary indexes on foreign keys
- Composite indexes for common query patterns
- Partial indexes for active records
- GIN indexes for JSONB search
- Covering indexes for dashboard queries
### Partitioning Strategy
- Activities table partitioned by month
- Audit log partitioned by month
- Automatic partition creation via cron job
### Connection Pooling
```sql
-- Recommended PostgreSQL settings
max_connections = 200
shared_buffers = 256MB
effective_cache_size = 1GB
work_mem = 4MB
```

View File

@@ -1,586 +0,0 @@
# UI/UX Design System - Maternal Organization App
## Design Philosophy
### Core Principles
- **Calm Clarity**: Modern minimalist approach reducing cognitive load
- **Warm Touch**: Nurturing colors and gentle interactions providing emotional comfort
- **One-Handed First**: All critical actions accessible within thumb reach
- **Interruption-Resilient**: Every interaction can be abandoned and resumed
- **Inclusive by Default**: WCAG AA/AAA compliance throughout
---
## Color System
### Primary Palette
```css
/* Warm Nurturing Colors */
--primary-peach: #FFB5A0;
--primary-coral: #FF8B7D;
--primary-rose: #FFD4CC;
--primary-blush: #FFF0ED;
/* Semantic Colors */
--success-sage: #7FB069;
--warning-amber: #F4A259;
--error-soft: #E07A5F;
--info-sky: #81C3D7;
/* Neutral Scale */
--neutral-900: #1A1A1A; /* Primary text */
--neutral-700: #404040; /* Secondary text */
--neutral-500: #737373; /* Disabled text */
--neutral-300: #D4D4D4; /* Borders */
--neutral-100: #F5F5F5; /* Backgrounds */
--neutral-50: #FAFAFA; /* Surface */
--white: #FFFFFF;
```
### Dark Mode Palette
```css
/* Dark Mode Adjustments */
--dark-surface: #1E1E1E;
--dark-elevated: #2A2A2A;
--dark-primary: #FFB5A0; /* Same warm colors */
--dark-text-primary: #F5F5F5;
--dark-text-secondary: #B8B8B8;
--dark-border: #404040;
```
### Color Usage Guidelines
- **Primary actions**: `--primary-coral`
- **Secondary actions**: `--primary-peach`
- **Backgrounds**: `--primary-blush` (10% opacity overlays)
- **Success states**: `--success-sage`
- **Warnings**: `--warning-amber`
- **Errors**: `--error-soft` (gentler than harsh red)
---
## Typography
### Font Families
```css
/* Sans-serif for UI elements */
--font-ui: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
/* Serif for content and insights */
--font-content: 'Crimson Pro', 'Georgia', serif;
/* Monospace for data */
--font-mono: 'JetBrains Mono', 'SF Mono', monospace;
```
### Type Scale (Material Design)
```css
/* Headlines */
--headline-1: 96px, light, -1.5px; /* Not used in mobile */
--headline-2: 60px, light, -0.5px; /* Not used in mobile */
--headline-3: 48px, regular, 0px; /* Not used in mobile */
--headline-4: 34px, regular, 0.25px; /* Screen titles */
--headline-5: 24px, regular, 0px; /* Section headers */
--headline-6: 20px, medium, 0.15px; /* Card titles */
/* Body Text */
--body-1: 16px, regular, 0.5px, 1.5 line-height; /* Main content */
--body-2: 14px, regular, 0.25px, 1.43 line-height; /* Secondary content */
/* Supporting Text */
--subtitle-1: 16px, medium, 0.15px; /* List items */
--subtitle-2: 14px, medium, 0.1px; /* Sub-headers */
--button: 14px, medium, 1.25px, uppercase;
--caption: 12px, regular, 0.4px; /* Timestamps, labels */
--overline: 10px, regular, 1.5px, uppercase;
```
### Mobile-Optimized Sizes
```css
/* Minimum touch target: 44x44px (iOS) / 48x48dp (Android) */
--text-minimum: 14px; /* Never smaller */
--text-comfortable: 16px; /* Default body */
--text-large: 18px; /* Easy reading */
```
---
## Spacing System
### Base Unit: 8px Grid
```css
--space-0: 0px;
--space-1: 8px;
--space-2: 16px;
--space-3: 24px;
--space-4: 32px;
--space-5: 40px;
--space-6: 48px;
--space-8: 64px;
--space-10: 80px;
```
### Component Spacing
```css
/* Padding */
--padding-button: 16px 24px;
--padding-card: 16px;
--padding-screen: 16px;
--padding-input: 12px 16px;
/* Margins */
--margin-section: 32px;
--margin-element: 16px;
--margin-text: 8px;
```
---
## Layout Grid
### Mobile Layout
```css
/* Screen Breakpoints */
--screen-small: 320px; /* iPhone SE */
--screen-medium: 375px; /* iPhone 12/13 */
--screen-large: 414px; /* iPhone Plus/Pro Max */
--screen-tablet: 768px; /* iPad */
/* Content Zones */
.safe-area {
padding-top: env(safe-area-inset-top);
padding-bottom: env(safe-area-inset-bottom);
}
.thumb-zone {
/* Bottom 60% of screen */
position: fixed;
bottom: 0;
height: 60vh;
}
```
### One-Handed Reachability Map
```
┌─────────────────────┐
│ Hard to reach │ 20%
├─────────────────────┤
│ Moderate reach │ 20%
├─────────────────────┤
│ Easy reach │ 30%
├─────────────────────┤
│ Natural reach │ 30%
│ (Thumb zone) │
└─────────────────────┘
```
---
## Component Specifications
### Buttons
#### Primary Button
```css
.button-primary {
background: var(--primary-coral);
color: white;
border-radius: 24px; /* Pill shape */
padding: 16px 32px;
min-height: 48px; /* Touch target */
font: var(--button);
box-shadow: 0 4px 8px rgba(255, 139, 125, 0.3);
}
```
#### Floating Action Button (FAB)
```css
.fab {
position: fixed;
bottom: 80px; /* Above navigation */
right: 16px;
width: 56px;
height: 56px;
border-radius: 28px;
background: var(--primary-coral);
box-shadow: 0 6px 12px rgba(0,0,0,0.15);
}
```
### Cards (Material Design)
```css
.card {
background: var(--white);
border-radius: 16px; /* Softer than Material default */
padding: var(--padding-card);
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
margin-bottom: var(--space-2);
}
.card-dark {
background: var(--dark-elevated);
box-shadow: 0 2px 8px rgba(0,0,0,0.3);
}
```
### Input Fields
```css
.input-field {
background: var(--neutral-50);
border: 2px solid transparent;
border-radius: 12px;
padding: var(--padding-input);
font-size: 16px; /* Prevents zoom on iOS */
min-height: 48px;
transition: all 0.2s ease;
}
.input-field:focus {
border-color: var(--primary-peach);
background: var(--white);
}
```
### Bottom Navigation
```css
.bottom-nav {
position: fixed;
bottom: 0;
width: 100%;
height: 64px;
background: var(--white);
box-shadow: 0 -2px 8px rgba(0,0,0,0.1);
display: flex;
justify-content: space-around;
padding-bottom: env(safe-area-inset-bottom);
}
.nav-item {
min-width: 64px;
display: flex;
flex-direction: column;
align-items: center;
padding: 8px;
}
```
---
## Icon System
### Icon Library: Material Icons Outlined
```css
/* Sizes */
--icon-small: 20px;
--icon-medium: 24px; /* Default */
--icon-large: 32px;
--icon-xlarge: 48px;
/* Styles */
.icon {
stroke-width: 1.5px;
color: var(--neutral-700);
}
.icon-primary {
color: var(--primary-coral);
}
```
### Core Icon Set
```
Navigation:
- home_outlined
- calendar_month_outlined
- insights_outlined
- chat_bubble_outline
- person_outline
Actions:
- add_circle_outline
- mic_outlined
- camera_outlined
- timer_outlined
- check_circle_outline
Tracking:
- baby_changing_station_outlined
- bed_outlined
- restaurant_outlined
- straighten_outlined (growth)
- medical_services_outlined
```
---
## Interaction Patterns
### Touch Targets
```css
/* Minimum touch target size */
.touchable {
min-width: 44px; /* iOS HIG */
min-height: 44px;
padding: 12px; /* Extends touch area */
}
```
### Gesture Support
```javascript
/* Swipe Actions */
- Swipe left: Delete/Archive
- Swipe right: Edit/Complete
- Pull down: Refresh
- Long press: Context menu
- Pinch: Zoom charts
```
### Loading States
```css
/* Skeleton Screens */
.skeleton {
background: linear-gradient(
90deg,
var(--neutral-100) 25%,
var(--neutral-50) 50%,
var(--neutral-100) 75%
);
background-size: 200% 100%;
animation: loading 1.5s infinite;
}
/* Spinner for actions */
.spinner {
width: 24px;
height: 24px;
border: 3px solid var(--primary-rose);
border-top-color: var(--primary-coral);
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
```
### Micro-Animations
```css
/* Gentle transitions */
* {
transition-duration: 0.2s;
transition-timing-function: ease-out;
}
/* Success feedback */
@keyframes success-pulse {
0% { transform: scale(1); }
50% { transform: scale(1.05); }
100% { transform: scale(1); }
}
```
---
## Accessibility Specifications
### WCAG Compliance
```css
/* Contrast Ratios */
--contrast-normal: 4.5:1; /* AA standard */
--contrast-large: 3:1; /* AA for large text */
--contrast-enhanced: 7:1; /* AAA standard */
/* Focus Indicators */
:focus-visible {
outline: 3px solid var(--primary-coral);
outline-offset: 2px;
}
```
### Screen Reader Support
```html
<!-- Proper ARIA labels -->
<button aria-label="Log feeding" aria-pressed="false">
<icon name="restaurant_outlined" aria-hidden="true" />
</button>
<!-- Live regions for updates -->
<div role="status" aria-live="polite" aria-atomic="true">
Activity logged successfully
</div>
```
### Reduced Motion
```css
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
```
---
## Platform-Specific Adaptations
### Material You (Android 12+)
```kotlin
// Dynamic color extraction
MaterialTheme(
colorScheme = dynamicColorScheme ?: customColorScheme,
typography = AppTypography,
content = content
)
```
### iOS Adaptations
```swift
// Haptic feedback
UIImpactFeedbackGenerator(style: .light).impactOccurred()
// Safe area handling
.edgesIgnoringSafeArea(.bottom)
```
---
## Dark Mode Implementation
### Automatic Switching
```javascript
// React Native
import { useColorScheme } from 'react-native';
const ColorScheme = {
light: {
background: '#FFFFFF',
text: '#1A1A1A',
primary: '#FF8B7D'
},
dark: {
background: '#1E1E1E',
text: '#F5F5F5',
primary: '#FFB5A0'
}
};
```
### Theme Provider
```typescript
// Material-UI Theme
const theme = createTheme({
palette: {
mode: systemPreference,
primary: {
main: '#FF8B7D',
},
background: {
default: mode === 'dark' ? '#1E1E1E' : '#FFFFFF',
},
},
typography: {
fontFamily: ['Inter', 'sans-serif'].join(','),
},
shape: {
borderRadius: 12,
},
});
```
---
## Component States
### Interactive States
```css
/* Default */
.button { opacity: 1; }
/* Hover (web) */
.button:hover { opacity: 0.9; }
/* Active/Pressed */
.button:active { transform: scale(0.98); }
/* Disabled */
.button:disabled {
opacity: 0.5;
cursor: not-allowed;
}
/* Loading */
.button.loading {
pointer-events: none;
color: transparent;
}
```
### Form Validation States
```css
.input-success {
border-color: var(--success-sage);
}
.input-error {
border-color: var(--error-soft);
background-color: rgba(224, 122, 95, 0.05);
}
.helper-text {
font-size: 12px;
color: var(--neutral-700);
margin-top: 4px;
}
```
---
## Quick Action Design
### Bottom Sheet Actions
```css
.quick-actions {
position: fixed;
bottom: 80px; /* Above nav */
left: 50%;
transform: translateX(-50%);
display: flex;
gap: 16px;
padding: 16px;
background: var(--white);
border-radius: 24px;
box-shadow: 0 8px 24px rgba(0,0,0,0.15);
}
.quick-action-button {
width: 64px;
height: 64px;
border-radius: 32px;
display: flex;
align-items: center;
justify-content: center;
background: var(--primary-blush);
}
```
---
## Performance Guidelines
### Image Optimization
- Maximum image size: 200KB
- Lazy loading for all images
- WebP format with JPG fallback
- Thumbnail generation for avatars
### Animation Performance
- Use transform and opacity only
- 60fps target for all animations
- GPU acceleration for transitions
- Avoid animating during scroll
### Font Loading
```css
@font-face {
font-family: 'Inter';
font-display: swap; /* Show fallback immediately */
src: url('/fonts/Inter.woff2') format('woff2');
}
```

View File

@@ -1,507 +0,0 @@
# Environment Configuration Guide - Maternal Organization App
## Environment Structure
### Environment Types
- **Development** (`dev`): Local development with hot reload
- **Staging** (`staging`): Pre-production testing environment
- **Production** (`prod`): Live application environment
- **Testing** (`test`): Automated testing environment
---
## Backend Environment Variables (.env)
### Core Configuration
```bash
# Application
NODE_ENV=development
APP_NAME=MaternalApp
APP_VERSION=1.0.0
API_VERSION=v1
PORT=3000
HOST=localhost
# URLs
BACKEND_URL=http://localhost:3000
FRONTEND_URL=http://localhost:8081
WEBSOCKET_URL=ws://localhost:3000
```
### Database Configuration
```bash
# PostgreSQL Primary
DATABASE_URL=postgresql://user:password@localhost:5432/maternal_app
DB_HOST=localhost
DB_PORT=5432
DB_NAME=maternal_app
DB_USER=maternal_user
DB_PASSWORD=secure_password_here
DB_SSL=false
DB_POOL_MIN=2
DB_POOL_MAX=10
# MongoDB (AI Chat History)
MONGODB_URI=mongodb://localhost:27017/maternal_ai
MONGODB_DB=maternal_ai
# Redis
REDIS_URL=redis://localhost:6379
REDIS_PASSWORD=
REDIS_DB=0
REDIS_CACHE_TTL=3600
```
### Authentication & Security
```bash
# JWT Configuration
JWT_SECRET=your-256-bit-secret-key-here
JWT_REFRESH_SECRET=different-256-bit-secret-key-here
JWT_EXPIRES_IN=1h
JWT_REFRESH_EXPIRES_IN=30d
# Encryption
ENCRYPTION_KEY=32-character-encryption-key-here
ENCRYPTION_IV=16-character-iv-here
# Device Fingerprinting
FINGERPRINT_SECRET=device-fingerprint-secret-key
# Rate Limiting
RATE_LIMIT_WINDOW_MS=60000
RATE_LIMIT_MAX_REQUESTS=100
```
### AI Services
```bash
# OpenAI
OPENAI_API_KEY=sk-your-openai-api-key
OPENAI_MODEL=gpt-4
OPENAI_TEMPERATURE=0.7
OPENAI_MAX_TOKENS=1000
# Anthropic Claude (Alternative)
ANTHROPIC_API_KEY=sk-ant-your-anthropic-key
ANTHROPIC_MODEL=claude-3-opus-20240229
# Whisper (Voice Recognition)
WHISPER_API_KEY=your-whisper-api-key
WHISPER_MODEL=whisper-1
# LangChain
LANGCHAIN_TRACING_V2=true
LANGCHAIN_API_KEY=your-langchain-api-key
LANGCHAIN_PROJECT=maternal-app
```
### External Services
```bash
# Email Service (SendGrid)
SENDGRID_API_KEY=SG.your-sendgrid-api-key
SENDGRID_FROM_EMAIL=support@maternalapp.com
SENDGRID_FROM_NAME=Maternal App
# Push Notifications
FCM_SERVER_KEY=your-firebase-server-key
FCM_PROJECT_ID=maternal-app-prod
APNS_KEY_ID=your-apple-key-id
APNS_TEAM_ID=your-apple-team-id
# File Storage (MinIO/S3)
S3_ENDPOINT=http://localhost:9000
S3_ACCESS_KEY=minioadmin
S3_SECRET_KEY=minioadmin
S3_BUCKET=maternal-uploads
S3_REGION=us-east-1
S3_USE_SSL=false
# Monitoring
SENTRY_DSN=https://your-sentry-dsn@sentry.io/project-id
SENTRY_ENVIRONMENT=development
SENTRY_TRACES_SAMPLE_RATE=0.1
```
### Compliance & Analytics
```bash
# COPPA/GDPR
COPPA_VERIFICATION_REQUIRED=true
GDPR_ENABLED=true
DATA_RETENTION_DAYS=365
AUDIT_LOG_ENABLED=true
# Analytics
MIXPANEL_TOKEN=your-mixpanel-token
GA_TRACKING_ID=G-XXXXXXXXXX
POSTHOG_API_KEY=your-posthog-key
POSTHOG_HOST=https://app.posthog.com
```
---
## Frontend Environment Variables (.env)
### React Native Configuration
```bash
# API Configuration
REACT_APP_API_BASE_URL=http://localhost:3000/api/v1
REACT_APP_GRAPHQL_URL=http://localhost:3000/graphql
REACT_APP_WS_URL=ws://localhost:3000/ws
# Feature Flags
REACT_APP_ENABLE_VOICE=true
REACT_APP_ENABLE_AI_CHAT=true
REACT_APP_ENABLE_DARK_MODE=true
REACT_APP_ENABLE_OFFLINE=true
REACT_APP_MAX_CHILDREN_FREE=2
REACT_APP_AI_QUERIES_FREE=10
# App Configuration
REACT_APP_NAME=Maternal
REACT_APP_VERSION=1.0.0
REACT_APP_BUILD_NUMBER=1
REACT_APP_BUNDLE_ID=com.maternalapp.app
```
### Platform-Specific (iOS)
```bash
# iOS Configuration
IOS_APP_ID=1234567890
IOS_TEAM_ID=XXXXXXXXXX
IOS_PROVISIONING_PROFILE=maternal-app-dev
APPLE_SIGN_IN_SERVICE_ID=com.maternalapp.signin
```
### Platform-Specific (Android)
```bash
# Android Configuration
ANDROID_PACKAGE_NAME=com.maternalapp.app
ANDROID_KEYSTORE_PATH=./android/app/maternal.keystore
ANDROID_KEY_ALIAS=maternal-key
ANDROID_KEYSTORE_PASSWORD=keystore-password
ANDROID_KEY_PASSWORD=key-password
```
---
## Docker Environment Configuration
### docker-compose.yml
```yaml
version: '3.8'
services:
postgres:
image: postgres:15-alpine
environment:
POSTGRES_DB: ${DB_NAME}
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "5432:5432"
redis:
image: redis:7-alpine
command: redis-server --requirepass ${REDIS_PASSWORD}
ports:
- "6379:6379"
mongodb:
image: mongo:6
environment:
MONGO_INITDB_DATABASE: maternal_ai
volumes:
- mongo_data:/data/db
ports:
- "27017:27017"
minio:
image: minio/minio
command: server /data --console-address ":9001"
environment:
MINIO_ROOT_USER: ${S3_ACCESS_KEY}
MINIO_ROOT_PASSWORD: ${S3_SECRET_KEY}
volumes:
- minio_data:/data
ports:
- "9000:9000"
- "9001:9001"
volumes:
postgres_data:
mongo_data:
minio_data:
```
---
## Secret Management
### Development Secrets (.env.local)
```bash
# Never commit this file
# Copy from .env.example and fill with real values
cp .env.example .env.local
```
### Production Secrets (AWS Secrets Manager)
```bash
# Store production secrets in AWS Secrets Manager
aws secretsmanager create-secret \
--name maternal-app/production \
--secret-string file://secrets.json
# Retrieve secrets in application
aws secretsmanager get-secret-value \
--secret-id maternal-app/production
```
### Kubernetes Secrets
```yaml
apiVersion: v1
kind: Secret
metadata:
name: maternal-app-secrets
type: Opaque
data:
jwt-secret: <base64-encoded-secret>
database-url: <base64-encoded-url>
openai-api-key: <base64-encoded-key>
```
---
## Environment File Templates
### .env.example (Commit to repo)
```bash
# Copy this file to .env.local and fill in values
NODE_ENV=development
PORT=3000
# Database
DATABASE_URL=postgresql://user:password@localhost:5432/maternal_app
# Add all variables with placeholder values...
JWT_SECRET=change-this-to-random-256-bit-key
OPENAI_API_KEY=sk-your-api-key-here
```
### .env.test (Testing)
```bash
NODE_ENV=test
DATABASE_URL=postgresql://test:test@localhost:5432/maternal_test
REDIS_URL=redis://localhost:6380
JWT_SECRET=test-jwt-secret-not-for-production
```
---
## Platform-Specific Configuration
### iOS Info.plist Additions
```xml
<key>API_BASE_URL</key>
<string>$(API_BASE_URL)</string>
<key>NSMicrophoneUsageDescription</key>
<string>Voice input for hands-free logging</string>
<key>NSCameraUsageDescription</key>
<string>Take photos of your child</string>
```
### Android gradle.properties
```properties
API_BASE_URL=http://10.0.2.2:3000/api/v1
ENABLE_VOICE_INPUT=true
ENABLE_PROGUARD=false
```
---
## Configuration Loading Order
### Backend (Node.js)
```javascript
// config/index.ts
import dotenv from 'dotenv';
// Load in order of precedence
dotenv.config({ path: '.env.local' }); // Local overrides
dotenv.config({ path: `.env.${NODE_ENV}` }); // Environment specific
dotenv.config(); // Default values
export const config = {
app: {
name: process.env.APP_NAME || 'MaternalApp',
version: process.env.APP_VERSION || '1.0.0',
env: process.env.NODE_ENV || 'development',
},
// ... rest of config
};
```
### Frontend (React Native)
```javascript
// config/env.js
import Config from 'react-native-config';
export const ENV = {
dev: {
API_URL: 'http://localhost:3000/api/v1',
WS_URL: 'ws://localhost:3000/ws',
},
staging: {
API_URL: 'https://staging-api.maternalapp.com/api/v1',
WS_URL: 'wss://staging-api.maternalapp.com/ws',
},
prod: {
API_URL: 'https://api.maternalapp.com/api/v1',
WS_URL: 'wss://api.maternalapp.com/ws',
},
}[Config.ENV || 'dev'];
```
---
## Security Best Practices
### Secret Rotation Schedule
- **JWT Secrets**: Every 90 days
- **API Keys**: Every 180 days
- **Database Passwords**: Every 60 days
- **Encryption Keys**: Every year
### Environment Variable Validation
```typescript
// validateEnv.ts
import { cleanEnv, str, port, url, bool, num } from 'envalid';
export const env = cleanEnv(process.env, {
NODE_ENV: str({ choices: ['development', 'test', 'staging', 'production'] }),
PORT: port(),
DATABASE_URL: url(),
JWT_SECRET: str({ minLength: 32 }),
OPENAI_API_KEY: str(),
RATE_LIMIT_MAX_REQUESTS: num({ default: 100 }),
});
```
### Git Security
```bash
# .gitignore
.env
.env.*
!.env.example
secrets/
*.key
*.pem
*.p12
```
---
## Deployment Configuration
### Heroku
```json
// app.json
{
"env": {
"NODE_ENV": {
"value": "production"
},
"DATABASE_URL": {
"required": true
},
"JWT_SECRET": {
"generator": "secret"
}
}
}
```
### Docker Build Args
```dockerfile
ARG NODE_ENV=production
ARG API_VERSION=v1
ENV NODE_ENV=${NODE_ENV}
ENV API_VERSION=${API_VERSION}
```
### CI/CD Variables (GitHub Actions)
```yaml
env:
NODE_ENV: production
DATABASE_URL: ${{ secrets.DATABASE_URL }}
JWT_SECRET: ${{ secrets.JWT_SECRET }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
```
---
## Monitoring & Debugging
### Debug Configuration
```bash
# Development debugging
DEBUG=maternal:*
LOG_LEVEL=debug
PRETTY_LOGS=true
# Production
LOG_LEVEL=info
LOG_FORMAT=json
```
### Health Check Variables
```bash
HEALTH_CHECK_INTERVAL=30000
HEALTH_CHECK_TIMEOUT=3000
HEALTH_CHECK_PATH=/health
```
---
## Quick Start Commands
### Local Development Setup
```bash
# 1. Copy environment template
cp .env.example .env.local
# 2. Start Docker services
docker-compose up -d
# 3. Run migrations
npm run migrate:up
# 4. Seed development data
npm run seed:dev
# 5. Start development server
npm run dev
```
### Environment Verification
```bash
# Check all required variables are set
npm run env:validate
# Display current configuration (masked)
npm run env:debug
```
---
## Troubleshooting
### Common Issues
1. **Missing API Keys**: Ensure all AI service keys are valid
2. **Database Connection**: Check DATABASE_URL format and credentials
3. **Redis Connection**: Verify Redis is running and accessible
4. **CORS Issues**: Confirm FRONTEND_URL is correctly set
5. **WebSocket Failures**: Check WS_URL matches backend configuration

View File

@@ -1,588 +0,0 @@
# Error Handling & Logging Standards - Maternal Organization App
## Error Philosophy
### Core Principles
- **Parent-Friendly Messages**: Never show technical jargon to users
- **Graceful Degradation**: App remains usable even with errors
- **Recovery Guidance**: Always suggest next steps
- **Preserve User Work**: Never lose unsaved data due to errors
- **Privacy First**: Never log sensitive data (PII, health info)
---
## Error Code Hierarchy
### Error Code Structure
Format: `[CATEGORY]_[SPECIFIC_ERROR]`
### Categories
```typescript
enum ErrorCategory {
AUTH = 'AUTH', // Authentication/Authorization
VALIDATION = 'VAL', // Input validation
SYNC = 'SYNC', // Synchronization issues
NETWORK = 'NET', // Network/connectivity
DATA = 'DATA', // Database/storage
AI = 'AI', // AI service errors
LIMIT = 'LIMIT', // Rate limiting/quotas
PAYMENT = 'PAY', // Subscription/payment
SYSTEM = 'SYS', // System/internal errors
COMPLIANCE = 'COMP' // COPPA/GDPR compliance
}
```
### Complete Error Code Registry
```typescript
export const ErrorCodes = {
// Authentication
AUTH_INVALID_CREDENTIALS: 'AUTH_001',
AUTH_TOKEN_EXPIRED: 'AUTH_002',
AUTH_TOKEN_INVALID: 'AUTH_003',
AUTH_DEVICE_NOT_TRUSTED: 'AUTH_004',
AUTH_MFA_REQUIRED: 'AUTH_005',
AUTH_ACCOUNT_LOCKED: 'AUTH_006',
// Validation
VAL_REQUIRED_FIELD: 'VAL_001',
VAL_INVALID_EMAIL: 'VAL_002',
VAL_WEAK_PASSWORD: 'VAL_003',
VAL_INVALID_DATE: 'VAL_004',
VAL_FUTURE_BIRTHDATE: 'VAL_005',
VAL_INVALID_AMOUNT: 'VAL_006',
// Sync
SYNC_CONFLICT: 'SYNC_001',
SYNC_OFFLINE_QUEUE_FULL: 'SYNC_002',
SYNC_VERSION_MISMATCH: 'SYNC_003',
SYNC_FAMILY_UPDATE_FAILED: 'SYNC_004',
// Network
NET_OFFLINE: 'NET_001',
NET_TIMEOUT: 'NET_002',
NET_SERVER_ERROR: 'NET_003',
NET_SLOW_CONNECTION: 'NET_004',
// AI
AI_SERVICE_UNAVAILABLE: 'AI_001',
AI_QUOTA_EXCEEDED: 'AI_002',
AI_INAPPROPRIATE_REQUEST: 'AI_003',
AI_CONTEXT_TOO_LARGE: 'AI_004',
// Limits
LIMIT_RATE_EXCEEDED: 'LIMIT_001',
LIMIT_CHILDREN_EXCEEDED: 'LIMIT_002',
LIMIT_FAMILY_SIZE_EXCEEDED: 'LIMIT_003',
LIMIT_STORAGE_EXCEEDED: 'LIMIT_004',
// Compliance
COMP_PARENTAL_CONSENT_REQUIRED: 'COMP_001',
COMP_AGE_VERIFICATION_FAILED: 'COMP_002',
COMP_DATA_RETENTION_EXPIRED: 'COMP_003'
};
```
---
## User-Facing Error Messages
### Message Structure
```typescript
interface UserErrorMessage {
title: string; // Brief, clear title
message: string; // Detailed explanation
action?: string; // What user should do
retryable: boolean; // Can user retry?
severity: 'info' | 'warning' | 'error';
}
```
### Localized Error Messages
```typescript
// errors/locales/en-US.json
{
"AUTH_001": {
"title": "Sign in failed",
"message": "The email or password you entered doesn't match our records.",
"action": "Please check your credentials and try again.",
"retryable": true
},
"SYNC_001": {
"title": "Update conflict",
"message": "This activity was updated by another family member.",
"action": "We've merged the changes. Please review.",
"retryable": false
},
"AI_002": {
"title": "AI assistant limit reached",
"message": "You've used all 10 free AI questions today.",
"action": "Upgrade to Premium for unlimited questions.",
"retryable": false
},
"NET_001": {
"title": "You're offline",
"message": "Don't worry! Your activities are saved locally.",
"action": "They'll sync when you're back online.",
"retryable": true
}
}
```
### Localization for Other Languages
```typescript
// errors/locales/es-ES.json
{
"AUTH_001": {
"title": "Error al iniciar sesión",
"message": "El correo o contraseña no coinciden con nuestros registros.",
"action": "Por favor verifica tus credenciales e intenta nuevamente.",
"retryable": true
}
}
// errors/locales/fr-FR.json
{
"AUTH_001": {
"title": "Échec de connexion",
"message": "L'email ou le mot de passe ne correspond pas.",
"action": "Veuillez vérifier vos identifiants et réessayer.",
"retryable": true
}
}
```
---
## Logging Strategy
### Log Levels
```typescript
enum LogLevel {
DEBUG = 0, // Development only
INFO = 1, // General information
WARN = 2, // Warning conditions
ERROR = 3, // Error conditions
FATAL = 4 // System is unusable
}
// Environment-based levels
const LOG_LEVELS = {
development: LogLevel.DEBUG,
staging: LogLevel.INFO,
production: LogLevel.WARN
};
```
### Structured Logging Format
```typescript
interface LogEntry {
timestamp: string;
level: LogLevel;
service: string;
userId?: string; // Hashed for privacy
familyId?: string; // For family-related issues
deviceId?: string; // Device fingerprint
errorCode?: string;
message: string;
context?: Record<string, any>;
stack?: string;
duration?: number; // For performance logs
correlationId: string; // Trace requests
}
// Example log entry
{
"timestamp": "2024-01-10T14:30:00.123Z",
"level": "ERROR",
"service": "ActivityService",
"userId": "hash_2n4k8m9p",
"errorCode": "SYNC_001",
"message": "Sync conflict detected",
"context": {
"activityId": "act_123",
"conflictType": "simultaneous_edit"
},
"correlationId": "req_8k3m9n2p"
}
```
### Logger Implementation
```typescript
// logger/index.ts
import winston from 'winston';
const logger = winston.createLogger({
level: process.env.LOG_LEVEL || 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.errors({ stack: true }),
winston.format.json()
),
defaultMeta: {
service: process.env.SERVICE_NAME,
version: process.env.APP_VERSION
},
transports: [
new winston.transports.Console({
format: winston.format.simple(),
silent: process.env.NODE_ENV === 'test'
}),
new winston.transports.File({
filename: 'error.log',
level: 'error'
})
]
});
// Privacy wrapper
export const log = {
info: (message: string, meta?: any) => {
logger.info(message, sanitizePII(meta));
},
error: (message: string, error: Error, meta?: any) => {
logger.error(message, {
...sanitizePII(meta),
errorMessage: error.message,
stack: error.stack
});
}
};
```
---
## Sentry Configuration
### Sentry Setup
```typescript
// sentry.config.ts
import * as Sentry from '@sentry/node';
Sentry.init({
dsn: process.env.SENTRY_DSN,
environment: process.env.NODE_ENV,
integrations: [
new Sentry.Integrations.Http({ tracing: true }),
new Sentry.Integrations.Express({ app }),
],
tracesSampleRate: process.env.NODE_ENV === 'production' ? 0.1 : 1.0,
beforeSend(event, hint) {
// Remove sensitive data
if (event.request) {
delete event.request.cookies;
delete event.request.headers?.authorization;
}
// Filter out user-caused errors
if (event.exception?.values?.[0]?.type === 'ValidationError') {
return null; // Don't send to Sentry
}
return sanitizeEvent(event);
},
ignoreErrors: [
'NetworkError',
'Request aborted',
'Non-Error promise rejection'
]
});
```
### React Native Sentry
```typescript
// Mobile sentry config
import * as Sentry from '@sentry/react-native';
Sentry.init({
dsn: process.env.SENTRY_DSN,
debug: __DEV__,
environment: __DEV__ ? 'development' : 'production',
attachScreenshot: true,
attachViewHierarchy: true,
beforeSend: (event) => {
// Don't send events in dev
if (__DEV__) return null;
// Remove sensitive context
delete event.user?.email;
delete event.contexts?.app?.device_name;
return event;
}
});
```
---
## Error Recovery Procedures
### Automatic Recovery
```typescript
// services/errorRecovery.ts
class ErrorRecoveryService {
async handleError(error: AppError): Promise<RecoveryAction> {
switch (error.code) {
case 'NET_OFFLINE':
return this.queueForOfflineSync(error.context);
case 'AUTH_TOKEN_EXPIRED':
return this.refreshToken();
case 'SYNC_CONFLICT':
return this.resolveConflict(error.context);
case 'AI_SERVICE_UNAVAILABLE':
return this.fallbackToOfflineAI();
default:
return this.defaultRecovery(error);
}
}
private async queueForOfflineSync(context: any) {
await offlineQueue.add(context);
return {
recovered: true,
message: 'Saved locally, will sync when online'
};
}
}
```
### User-Guided Recovery
```typescript
// components/ErrorBoundary.tsx
class ErrorBoundary extends React.Component {
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
// Log to Sentry
Sentry.captureException(error, { contexts: { react: errorInfo } });
// Show recovery UI
this.setState({
hasError: true,
error,
recovery: this.getRecoveryOptions(error)
});
}
render() {
if (this.state.hasError) {
return (
<ErrorRecoveryScreen
title={i18n.t('error.something_went_wrong')}
message={i18n.t('error.we_are_sorry')}
actions={[
{ label: 'Try Again', onPress: this.retry },
{ label: 'Go to Dashboard', onPress: this.reset },
{ label: 'Contact Support', onPress: this.support }
]}
/>
);
}
return this.props.children;
}
}
```
---
## Audit Logging
### COPPA/GDPR Compliance Logging
```typescript
interface AuditLog {
timestamp: string;
userId: string;
action: AuditAction;
entityType: string;
entityId: string;
changes?: Record<string, any>;
ipAddress: string;
userAgent: string;
result: 'success' | 'failure';
reason?: string;
}
enum AuditAction {
// Data access
VIEW_CHILD_DATA = 'VIEW_CHILD_DATA',
EXPORT_DATA = 'EXPORT_DATA',
// Data modification
CREATE_CHILD_PROFILE = 'CREATE_CHILD_PROFILE',
UPDATE_CHILD_DATA = 'UPDATE_CHILD_DATA',
DELETE_CHILD_DATA = 'DELETE_CHILD_DATA',
// Consent
GRANT_CONSENT = 'GRANT_CONSENT',
REVOKE_CONSENT = 'REVOKE_CONSENT',
// Account
DELETE_ACCOUNT = 'DELETE_ACCOUNT',
CHANGE_PASSWORD = 'CHANGE_PASSWORD'
}
```
### Audit Log Implementation
```sql
-- Audit log table with partitioning
CREATE TABLE audit_logs (
id BIGSERIAL,
timestamp TIMESTAMP NOT NULL,
user_id VARCHAR(20),
action VARCHAR(50) NOT NULL,
entity_type VARCHAR(50),
entity_id VARCHAR(20),
changes JSONB,
ip_address INET,
user_agent TEXT,
result VARCHAR(20),
PRIMARY KEY (id, timestamp)
) PARTITION BY RANGE (timestamp);
```
---
## Performance Monitoring
### Response Time Logging
```typescript
// middleware/performanceLogger.ts
export const performanceLogger = (req: Request, res: Response, next: Next) => {
const start = Date.now();
res.on('finish', () => {
const duration = Date.now() - start;
if (duration > 1000) { // Log slow requests
logger.warn('Slow request detected', {
method: req.method,
path: req.path,
duration,
statusCode: res.statusCode
});
// Send to monitoring
metrics.histogram('request.duration', duration, {
path: req.path,
method: req.method
});
}
});
next();
};
```
---
## Alert Configuration
### Critical Alerts
```yaml
# alerts/critical.yml
alerts:
- name: high_error_rate
condition: error_rate > 5%
duration: 5m
action: page_on_call
- name: auth_failures_spike
condition: auth_failures > 100
duration: 1m
action: security_team_alert
- name: ai_service_down
condition: ai_availability < 99%
duration: 2m
action: notify_team
- name: database_connection_pool_exhausted
condition: available_connections < 5
action: scale_database
```
---
## Client-Side Error Tracking
### React Native Global Handler
```typescript
// errorHandler.ts
import { setJSExceptionHandler } from 'react-native-exception-handler';
setJSExceptionHandler((error, isFatal) => {
if (isFatal) {
logger.fatal('Fatal JS error', { error });
Alert.alert(
'Unexpected error occurred',
'The app needs to restart. Your data has been saved.',
[{ text: 'Restart', onPress: () => RNRestart.Restart() }]
);
} else {
logger.error('Non-fatal JS error', { error });
// Show toast notification
Toast.show({
type: 'error',
text1: 'Something went wrong',
text2: 'Please try again'
});
}
}, true); // Allow in production
```
---
## Error Analytics Dashboard
### Key Metrics
```typescript
interface ErrorMetrics {
errorRate: number; // Errors per 1000 requests
errorTypes: Record<string, number>; // Count by error code
affectedUsers: number; // Unique users with errors
recoveryRate: number; // % of errors recovered
meanTimeToRecovery: number; // Seconds
criticalErrors: ErrorEvent[]; // P0 errors
}
// Monitoring queries
const getErrorMetrics = async (timeRange: TimeRange): Promise<ErrorMetrics> => {
const errors = await db.query(`
SELECT
COUNT(*) as total_errors,
COUNT(DISTINCT user_id) as affected_users,
AVG(recovery_time) as mttr,
error_code,
COUNT(*) as count
FROM error_logs
WHERE timestamp > $1
GROUP BY error_code
`, [timeRange.start]);
return processMetrics(errors);
};
```
---
## Development Error Tools
### Debug Mode Enhancements
```typescript
// Development only error overlay
if (__DEV__) {
// Show detailed error information
ErrorUtils.setGlobalHandler((error, isFatal) => {
console.group('🔴 Error Details');
console.error('Error:', error.message);
console.error('Stack:', error.stack);
console.error('Component Stack:', error.componentStack);
console.error('Fatal:', isFatal);
console.groupEnd();
});
// Network request inspector
global.XMLHttpRequest = decorateXHR(global.XMLHttpRequest);
}
```

View File

@@ -1,783 +0,0 @@
# Implementation Plan - AI-Powered Maternal Organization App
## AI Coding Assistant Role Guide
### How to Use This Document with AI
Each phase specifies a role for the AI assistant to adopt, ensuring appropriate expertise and focus. When starting a new phase, instruct the AI with the specified role prompt to get optimal results.
**Example Usage:**
```
"For this phase, act as a Senior Backend Architect with expertise in NestJS and PostgreSQL. Focus on security, scalability, and proper architectural patterns."
```
-----
## Phase 0: Development Environment Setup (Week 0)
### 🤖 AI Role: Senior DevOps Engineer & System Architect
```
"Act as a Senior DevOps Engineer with expertise in Docker, PostgreSQL, Redis, and cloud infrastructure. Focus on creating a robust, scalable development environment with proper security configurations."
```
### Infrastructure Setup
```bash
# Required installations - See Technical Stack document for complete list
- Node.js 18+ LTS
- React Native CLI
- Expo CLI
- Docker & Docker Compose
- PostgreSQL 15+
- Redis 7+
- MongoDB 6+ (for AI chat history)
- MinIO (for file storage)
- Git
```
### Project Initialization
```bash
# Frontend setup - Reference Technical Stack document
npx create-expo-app maternal-app --template
cd maternal-app
npm install react-navigation react-native-paper redux-toolkit
# Additional packages from Technical Stack document
# Backend setup
nest new maternal-app-backend
cd maternal-app-backend
npm install @nestjs/websockets @nestjs/typeorm @nestjs/jwt
```
### Development Tools Configuration
- Set up ESLint, Prettier, Husky
- Configure VS Code with recommended extensions
- Initialize Git repositories with .gitignore
- **Configure environment variables** - See Environment Configuration Guide for complete .env setup
- Configure Docker Compose - Use docker-compose.yml from Environment Configuration Guide
### AI Service Setup
- **Configure AI services** - See Environment Configuration Guide for API keys
- **LangChain setup** - See AI Context & Prompting Templates document
- Rate limiting configuration (100 requests/minute per user)
-----
## Phase 1: Foundation & Authentication (Week 1-2)
### 🤖 AI Role: Senior Backend Developer & Security Expert
```
"Act as a Senior Backend Developer specializing in NestJS, PostgreSQL, and JWT authentication. Focus on security best practices, OWASP compliance, and building a scalable authentication system with device fingerprinting."
```
### 1.1 Database Schema Design
```sql
-- Use complete schema from Database Migration Scripts document
-- Run migrations V001 through V007 in sequence
-- See Database Migration Scripts for rollback procedures
```
### 1.2 Authentication System
```typescript
// Backend: NestJS Auth Module
// Complete implementation in API Specification Document - Authentication Endpoints section
@Module({
imports: [
JwtModule.register({
secret: process.env.JWT_SECRET,
signOptions: { expiresIn: '1h' }, // Access token
// Refresh token handled separately - see API Specification
}),
PassportModule,
],
providers: [AuthService, JwtStrategy, LocalStrategy],
controllers: [AuthController],
})
export class AuthModule {}
// Implement endpoints from API Specification Document:
POST /api/v1/auth/register (with device fingerprinting)
POST /api/v1/auth/login
POST /api/v1/auth/refresh
POST /api/v1/auth/logout
```
### 1.3 Mobile Authentication UI
```typescript
// React Native Screens - Follow UI/UX Design System document
// Use Material Design components and warm color palette
- SplashScreen.tsx
- OnboardingScreen.tsx
- LoginScreen.tsx (implement design from UI/UX Design System)
- RegisterScreen.tsx
- ForgotPasswordScreen.tsx
// Key components with Material Design
- BiometricLogin component
- SocialLoginButtons (Google/Apple)
- SecureTextInput component (min-height: 48px for touch targets)
```
### 1.4 Internationalization Setup
```javascript
// i18n configuration - 5 languages from MVP Features document
// See Error Handling & Logging Standards for localized error messages
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
// Language files structure
/locales
/en-US
/es-ES
/fr-FR
/pt-BR
/zh-CN
```
### Deliverables Week 1-2
- [ ] Working authentication flow with JWT + Refresh tokens
- [ ] Device fingerprinting (see API Specification)
- [ ] Secure password storage with bcrypt
- [ ] Email verification system
- [ ] Multi-language support (5 languages)
- [ ] Material Design UI components
-----
## Phase 2: Child Profiles & Family Management (Week 2-3)
### 🤖 AI Role: Full-Stack Developer with Real-time Systems Experience
```
"Act as a Full-Stack Developer with expertise in React Native, NestJS, WebSockets, and Redis. Focus on building real-time synchronization, family data management, and responsive mobile UI with Material Design."
```
### 2.1 Child Profile CRUD Operations
```typescript
// API Endpoints - Full specifications in API Specification Document
// See "Children Management Endpoints" section for complete schemas
POST /api/v1/children
GET /api/v1/children/:id
PUT /api/v1/children/:id
DELETE /api/v1/children/:id
// Use State Management Schema for Redux structure
// Children slice with normalized state shape
```
### 2.2 Family Invitation System
```typescript
// Complete flow in API Specification Document - "Family Management Endpoints"
POST /api/v1/families/invite
POST /api/v1/families/join/:shareCode
// Error handling from Error Handling & Logging Standards
// Use error codes: LIMIT_FAMILY_SIZE_EXCEEDED, AUTH_DEVICE_NOT_TRUSTED
```
### 2.3 Real-time Family Sync Setup
```typescript
// WebSocket implementation - See API Specification Document "WebSocket Events"
// State sync via State Management Schema - Sync Slice
@WebSocketGateway()
export class FamilyGateway {
// Implementation details in API Specification
// Use sync middleware from State Management Schema
}
```
### 2.4 Mobile Family Management UI
```typescript
// Screens following UI/UX Design System
// Material Design with warm color palette (peach, coral, rose)
// Minimum touch targets: 44x44px
- FamilyDashboard.tsx (use card components from Design System)
- AddChildScreen.tsx (spacious layout for one-handed use)
- ChildProfileScreen.tsx
- InviteFamilyMember.tsx
- FamilySettings.tsx
```
-----
## Phase 3: Core Tracking Features (Week 3-4)
### 🤖 AI Role: Mobile Developer & Offline-First Systems Expert
```
"Act as a Senior Mobile Developer specializing in React Native, offline-first architecture, and voice interfaces. Focus on building intuitive tracking features with voice input, offline support, and seamless sync using Redux and SQLite."
```
### 3.1 Database Schema for Activities
```sql
-- Use Migration V003 from Database Migration Scripts document
-- Includes partitioned tables for scalability
-- Run performance optimization indexes from Migration V005
```
### 3.2 Activity Tracking Services
```typescript
// Backend services - See API Specification "Activity Tracking Endpoints"
// Implement all REST endpoints with proper error codes
@Injectable()
export class TrackingService {
// Use error codes from Error Handling & Logging Standards
// Implement offline queue from State Management Schema
async logFeeding(data: FeedingDto) {
// Follow API schema from specification
// Emit WebSocket events per API Specification
// Update Redux state per State Management Schema
}
}
```
### 3.3 Voice Input Integration
```typescript
// Complete implementation in Voice Input Processing Guide
// Multi-language patterns for all 5 MVP languages
// Whisper API configuration from Environment Configuration Guide
import { WhisperService } from './services/whisperService';
// Use natural language patterns from Voice Input Processing Guide
// Implement error recovery and clarification prompts
```
### 3.4 Tracking UI Components
```typescript
// Follow UI/UX Design System specifications
// Material Design components with warm palette
// One-handed operation optimization (bottom 60% of screen)
- QuickActionButtons.tsx (FAB positioning from Design System)
- FeedingTimer.tsx
- SleepTracker.tsx
- DiaperLogger.tsx
- ActivityTimeline.tsx (use skeleton screens for loading)
```
### 3.5 Offline Support Implementation
```typescript
// Complete offline architecture in State Management Schema
// See Offline Slice and middleware configuration
// Sync queue implementation from Sync Slice
```
-----
## Phase 4: AI Assistant Integration (Week 4-5)
### 🤖 AI Role: AI/ML Engineer & LLM Integration Specialist
```
"Act as an AI/ML Engineer with expertise in LangChain, OpenAI APIs, prompt engineering, and safety systems. Focus on building a helpful, safe, and contextually aware AI assistant with proper token management and response quality."
```
### Context Review:
```
"Also review as a Child Safety Expert to ensure all AI responses are appropriate for parenting contexts and include proper medical disclaimers."
```
### 4.1 LLM Service Setup
```typescript
// Complete LangChain configuration in AI Context & Prompting Templates document
// Use system prompts and safety boundaries from the document
import { initializeLangChain } from './config/langchain';
// See AI Context & Prompting Templates for:
// - Context window management (4000 tokens)
// - Safety boundaries and medical disclaimers
// - Personalization engine
```
### 4.2 Context Management System
```typescript
// Full implementation in AI Context & Prompting Templates
// Priority weighting system for context selection
class AIContextBuilder {
// Use ContextManager from AI Context & Prompting Templates
// Implements token counting and prioritization
// Child-specific context templates
}
```
### 4.3 Chat Interface Implementation
```typescript
// React Native Chat UI
// Follow UI/UX Design System for chat bubbles
// Implement localized responses from AI Context & Prompting Templates
const AIAssistantScreen = () => {
// Use conversation memory management from AI Context document
// Implement prompt injection protection
// Apply response formatting templates
};
```
### 4.4 Smart Notifications System
```typescript
// Use patterns from API Specification - Analytics & Insights Endpoints
// Schedule based on predictions from AI
class SmartNotificationService {
// Reference notification preferences from Database Migration V006
// Use push notification setup from Environment Configuration Guide
}
```
-----
## Phase 5: Pattern Recognition & Analytics (Week 5-6)
### 🤖 AI Role: Data Scientist & Analytics Engineer
```
"Act as a Data Scientist with expertise in time-series analysis, pattern recognition, and data visualization. Focus on building accurate prediction algorithms, meaningful insights extraction, and clear data presentation using React Native charts."
```
### Context Review:
```
"Review predictions as a Pediatric Data Analyst to ensure all insights are age-appropriate and medically sound."
```
### 5.1 Pattern Analysis Engine
```typescript
// Pattern detection algorithms referenced in API Specification
// See "Analytics & Insights Endpoints" for complete schemas
@Injectable()
export class PatternAnalysisService {
// GraphQL queries from API Specification for complex data
// Use AI Context & Prompting Templates for pattern insights
async analyzeSleepPatterns(childId: string) {
// Implement sleep prediction from Voice Input Processing Guide
// Store predictions in State Management Schema - AI Slice
}
}
```
### 5.2 Predictive Algorithms
```typescript
// Sleep prediction using patterns from API Specification
// Response format from "GET /api/v1/insights/{childId}/predictions"
class SleepPredictor {
// Algorithm matches Huckleberry's SweetSpot® approach
// 85% confidence target from API Specification
}
```
### 5.3 Analytics Dashboard
```typescript
// Dashboard Components using UI/UX Design System
// Material Design cards and charts
// Victory Native from Technical Stack document
- WeeklySleepChart.tsx (use warm color palette)
- FeedingFrequencyGraph.tsx
- GrowthCurve.tsx (WHO percentiles)
- PatternInsights.tsx
- ExportReport.tsx
```
### 5.4 Report Generation
```typescript
// PDF generation using libraries from Technical Stack
// GraphQL WeeklyReport query from API Specification
class ReportGenerator {
// Use report formatting from UI/UX Design System
// Include localized content for all 5 languages
}
```
-----
## Phase 6: Testing & Optimization (Week 6-7)
### 🤖 AI Role: QA Engineer & Performance Specialist
```
"Act as a Senior QA Engineer with expertise in Jest, Detox, performance testing, and accessibility compliance. Focus on comprehensive test coverage, performance optimization, and ensuring WCAG compliance."
```
### Context Reviews:
```
1. "Review as a Security Auditor for vulnerability assessment"
2. "Review as an Accessibility Expert for WCAG AA/AAA compliance"
3. "Review as a Performance Engineer for optimization opportunities"
```
### 6.1 Unit Testing Implementation
```typescript
// Complete testing strategy in Testing Strategy Document
// 80% code coverage requirement
// Use mock data structures from Testing Strategy Document
describe('TrackingService', () => {
// Test examples from Testing Strategy Document
// Use error codes from Error Handling & Logging Standards
});
describe('SleepPredictor', () => {
// Performance benchmarks from Testing Strategy Document
// 85% accuracy target for predictions
});
```
### 6.2 Integration Testing
```typescript
// E2E tests with Detox - See Testing Strategy Document
// Critical user journeys and offline sync testing
describe('Complete tracking flow', () => {
// Test WebSocket sync from API Specification
// Verify offline queue from State Management Schema
});
```
### 6.3 Performance Optimization
```typescript
// React Native optimizations from UI/UX Design System
// - 60fps scrolling requirement
// - 2-second max load time
// - Skeleton screens for loading states
// Backend optimizations from Database Migration Scripts
// - Partitioned tables for activities
// - Performance indexes from Migration V005
// - Redis caching from Environment Configuration
```
### 6.4 Security Audit
```bash
# Security checklist from multiple documents:
# - API Specification: Request signing, rate limiting
# - Environment Configuration: Secret rotation schedule
# - Database Migrations: COPPA/GDPR compliance tables
# - Error Handling: Audit logging implementation
```
-----
## Phase 7: Beta Testing & Launch Preparation (Week 7-8)
### 🤖 AI Role: DevOps Engineer & Mobile Deployment Specialist
```
"Act as a DevOps Engineer with expertise in CI/CD, mobile app deployment, TestFlight, Google Play Console, and production infrastructure. Focus on automated deployment pipelines, monitoring setup, and app store compliance."
```
### Context Review:
```
"Review as a Compliance Officer for COPPA/GDPR requirements and app store policies"
```
### 7.1 Beta Testing Program
```markdown
# Beta Testing Plan from Testing Strategy Document
- Recruit 50 diverse families (language/geography diversity)
- Testing groups from Mobile Build & Deployment Guide
- Use TestFlight/Play Console setup from Mobile Build & Deployment Guide
- Feedback collection via Testing Strategy Document metrics
```
### 7.2 App Store Preparation
```markdown
# Complete requirements from Mobile Build & Deployment Guide
# iOS App Store - see "TestFlight Configuration" section
# Google Play Store - see "Google Play Console Configuration" section
# Web App Implementation review
# Store assets using UI/UX Design System guidelines:
- Screenshots with warm color palette
- App icon with peach/coral branding
- Localized descriptions for 5 languages
```
### 7.3 Monitoring Setup
```typescript
// Sentry configuration from Environment Configuration Guide
// Error tracking setup from Error Handling & Logging Standards
import * as Sentry from '@sentry/react-native';
// Use Sentry DSN from Environment Configuration
// Implement error filtering from Error Handling document
// Analytics from Technical Stack document (PostHog/Matomo)
```
### 7.4 Production Infrastructure
```yaml
# Use docker-compose.yml from Environment Configuration Guide
# Add production settings from Mobile Build & Deployment Guide
# Include all services from Technical Stack:
# - PostgreSQL, MongoDB, Redis, MinIO, Front end web server
```
-----
## Phase 8: Launch & Post-Launch (Week 8+)
### 🤖 AI Role: Product Manager & Growth Engineer
```
"Act as a Product Manager with expertise in user analytics, growth strategies, and iterative development. Focus on monitoring key metrics, user feedback analysis, and rapid iteration based on real-world usage."
```
### Context Reviews:
```
1. "Analyze as a Data Analyst for user behavior patterns"
2. "Review as a Customer Success Manager for support improvements"
3. "Evaluate as a Growth Hacker for retention optimization"
```
### 8.1 Launch Checklist
```markdown
## Technical - Reference Mobile Build & Deployment Guide
- [ ] Production environment live (Environment Configuration Guide)
- [ ] SSL certificates configured
- [ ] CDN configured (Technical Stack - performance section)
- [ ] Backup systems tested (Database Migration Scripts - maintenance)
- [ ] Monitoring dashboards active (Error Handling & Logging Standards)
- [ ] Error tracking enabled (Sentry setup)
- [ ] Analytics tracking verified (PostHog/Matomo)
## Legal
- [ ] Privacy policy published (COPPA/GDPR from Database Migrations)
- [ ] Terms of service published
- [ ] Compliance verified (Audit tables from Migration V007)
## Support
- [ ] Help documentation complete
- [ ] Multi-language support ready (5 languages)
- [ ] Error messages localized (Error Handling document)
```
### 8.2 Post-Launch Monitoring
```typescript
// Key metrics from Testing Strategy Document
// Success criteria: 60% DAU, <2% crash rate, 4.0+ rating
const metrics = {
// Track via analytics setup from Environment Configuration
// Use error monitoring from Error Handling & Logging Standards
// Performance metrics from API Specification (p95 < 3s)
};
```
### 8.3 Rapid Iteration Plan
```markdown
# Use CodePush from Mobile Build & Deployment Guide for OTA updates
# Follow staged rollout strategy from Mobile Build & Deployment Guide
# Week 1-2: Monitor error codes from Error Handling document
# Week 3-4: UI improvements based on Design System principles
# Month 2: Premium features from MVP Features document
```
-----
## Development Best Practices
### Code Organization
```
/maternal-app
/src
/components
/common
/tracking
/ai
/screens
/services
/hooks
/utils
/redux
/slices
/actions
/locales
/navigation
/types
/maternal-app-backend
/src
/modules
/auth
/users
/families
/tracking
/ai
/common
/guards
/interceptors
/filters
/database
/entities
/migrations
```
### Git Workflow
```bash
# Branch naming
feature/track-feeding
bugfix/sync-issue
hotfix/crash-on-login
# Commit messages
feat: add voice input for feeding tracker
fix: resolve timezone sync issue
docs: update API documentation
test: add unit tests for sleep predictor
```
### CI/CD Pipeline
```yaml
# GitHub Actions example
name: CI/CD Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: npm install
- run: npm test
- run: npm run lint
build:
needs: test
runs-on: ubuntu-latest
steps:
- run: npm run build
- run: docker build
deploy:
needs: build
if: github.ref == 'refs/heads/main'
steps:
- run: ./deploy.sh
```
-----
## Risk Mitigation Strategies
### Technical Risks
1. **LLM API Downtime**
- Implement fallback to cached responses
- Queue queries for retry
- Basic rule-based responses as backup
1. **Scalability Issues**
- Start with vertical scaling capability
- Design for horizontal scaling from day 1
- Implement caching aggressively
1. **Data Loss**
- Automated backups every 6 hours
- Point-in-time recovery capability
- Multi-region backup storage
### Business Risks
1. **Low User Adoption**
- Quick onboarding (< 2 minutes)
- Immediate value demonstration
- Strong referral incentives
1. **High Churn Rate**
- Weekly engagement emails
- Push notification optimization
- Feature discovery prompts
1. **Competitive Pressure**
- Rapid feature iteration
- Strong AI differentiation
- Community building
-----
## Success Criteria
### MVP Launch Success
- 1,000 downloads in first month
- 60% day-7 retention
- 4.0+ app store rating
- <2% crash rate
- 5+ activities logged per day per active user
- 70% of users trying AI assistant
### 3-Month Goals
- 10,000 active users
- 500 premium subscribers
- 50% month-over-month growth
- 4.5+ app store rating
- 3 major feature updates
- 2 partnership agreements
### 6-Month Vision
- 50,000 active users
- 2,500 premium subscribers
- Break-even on operational costs
- International expansion (10+ countries)
- Integration ecosystem launched
- Series A fundraising ready

View File

@@ -1,590 +0,0 @@
# Mobile Build & Deployment Guide - Maternal Organization App
## Build Environment Setup
### Prerequisites
```bash
# Required tools
node >= 18.0.0
npm >= 9.0.0
react-native-cli >= 2.0.1
expo-cli >= 6.0.0
cocoapods >= 1.12.0 (iOS)
java 11 (Android)
android-studio (Android)
xcode >= 14.0 (iOS)
```
### Project Initialization
```bash
# Create project with Expo
npx create-expo-app maternal-app --template
# Install core dependencies
cd maternal-app
npm install react-native-reanimated react-native-gesture-handler
npm install react-native-safe-area-context react-native-screens
npm install @react-navigation/native @react-navigation/bottom-tabs
```
---
## iOS Configuration
### Bundle Identifier & Provisioning
```xml
<!-- ios/MaternalApp/Info.plist -->
<key>CFBundleIdentifier</key>
<string>com.maternalapp.ios</string>
<key>CFBundleDisplayName</key>
<string>Maternal</string>
<key>CFBundleShortVersionString</key>
<string>1.0.0</string>
<key>CFBundleVersion</key>
<string>1</string>
```
### App Capabilities
```xml
<!-- ios/MaternalApp/MaternalApp.entitlements -->
<?xml version="1.0" encoding="UTF-8"?>
<plist version="1.0">
<dict>
<key>aps-environment</key>
<string>production</string>
<key>com.apple.developer.healthkit</key>
<true/>
<key>com.apple.developer.healthkit.background-delivery</key>
<true/>
<key>com.apple.security.application-groups</key>
<array>
<string>group.com.maternalapp.shared</string>
</array>
</dict>
</plist>
```
### Permissions
```xml
<!-- ios/MaternalApp/Info.plist -->
<key>NSCameraUsageDescription</key>
<string>Take photos of your child for memories and milestone tracking</string>
<key>NSMicrophoneUsageDescription</key>
<string>Enable voice input for hands-free activity logging</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Select photos for your child's profile and milestones</string>
<key>NSSpeechRecognitionUsageDescription</key>
<string>Convert your voice to text for quick logging</string>
<key>NSHealthShareUsageDescription</key>
<string>Read health data to track your child's growth</string>
<key>NSHealthUpdateUsageDescription</key>
<string>Save growth measurements to Health app</string>
```
### Code Signing Configuration
```ruby
# ios/fastlane/Fastfile
platform :ios do
desc "Build and deploy to TestFlight"
lane :beta do
increment_build_number
match(
type: "appstore",
app_identifier: "com.maternalapp.ios",
git_url: "git@github.com:maternal-app/certificates.git"
)
gym(
scheme: "MaternalApp",
configuration: "Release",
export_method: "app-store",
output_directory: "./build",
output_name: "MaternalApp.ipa"
)
pilot(
ipa: "./build/MaternalApp.ipa",
skip_waiting_for_build_processing: true,
changelog: "Bug fixes and performance improvements"
)
end
end
```
---
## Android Configuration
### Package Name & Versioning
```gradle
// android/app/build.gradle
android {
compileSdkVersion 34
buildToolsVersion "34.0.0"
defaultConfig {
applicationId "com.maternalapp.android"
minSdkVersion 23 // Android 6.0
targetSdkVersion 34
versionCode 1
versionName "1.0.0"
multiDexEnabled true
}
signingConfigs {
release {
storeFile file(MATERNAL_RELEASE_STORE_FILE)
storePassword MATERNAL_RELEASE_STORE_PASSWORD
keyAlias MATERNAL_RELEASE_KEY_ALIAS
keyPassword MATERNAL_RELEASE_KEY_PASSWORD
}
}
buildTypes {
release {
signingConfig signingConfigs.release
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
```
### Permissions
```xml
<!-- android/app/src/main/AndroidManifest.xml -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<!-- Google Play Services -->
<uses-permission android:name="com.google.android.gms.permission.AD_ID" tools:node="remove" />
```
### ProGuard Rules
```pro
# android/app/proguard-rules.pro
-keep class com.maternalapp.** { *; }
-keep class com.facebook.react.** { *; }
-keep class com.swmansion.** { *; }
# React Native
-keep,allowobfuscation @interface com.facebook.proguard.annotations.DoNotStrip
-keep,allowobfuscation @interface com.facebook.proguard.annotations.KeepGettersAndSetters
# Firebase
-keep class com.google.firebase.** { *; }
-keep class com.google.android.gms.** { *; }
```
---
## Environment-Specific Builds
### Build Configurations
```javascript
// app.config.js
export default ({ config }) => {
const buildType = process.env.BUILD_TYPE || 'development';
const configs = {
development: {
name: 'Maternal (Dev)',
bundleIdentifier: 'com.maternalapp.dev',
apiUrl: 'https://dev-api.maternalapp.com',
icon: './assets/icon-dev.png',
},
staging: {
name: 'Maternal (Staging)',
bundleIdentifier: 'com.maternalapp.staging',
apiUrl: 'https://staging-api.maternalapp.com',
icon: './assets/icon-staging.png',
},
production: {
name: 'Maternal',
bundleIdentifier: 'com.maternalapp.ios',
apiUrl: 'https://api.maternalapp.com',
icon: './assets/icon.png',
},
};
return {
...config,
...configs[buildType],
ios: {
...config.ios,
bundleIdentifier: configs[buildType].bundleIdentifier,
buildNumber: '1',
},
android: {
...config.android,
package: configs[buildType].bundleIdentifier.replace('ios', 'android'),
versionCode: 1,
},
};
};
```
### Environment Variables
```bash
# .env.production
API_URL=https://api.maternalapp.com
SENTRY_DSN=https://prod-sentry.maternalapp.com
ANALYTICS_ENABLED=true
CRASH_REPORTING=true
# .env.staging
API_URL=https://staging-api.maternalapp.com
SENTRY_DSN=https://staging-sentry.maternalapp.com
ANALYTICS_ENABLED=true
CRASH_REPORTING=true
# .env.development
API_URL=http://localhost:3000
SENTRY_DSN=
ANALYTICS_ENABLED=false
CRASH_REPORTING=false
```
---
## CI/CD Pipeline
### GitHub Actions Workflow
```yaml
# .github/workflows/mobile-deploy.yml
name: Mobile Build & Deploy
on:
push:
branches: [main, staging]
tags: ['v*']
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
- run: npm ci
- run: npm test
- run: npm run lint
build-ios:
needs: test
runs-on: macos-latest
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')
steps:
- uses: actions/checkout@v3
- name: Setup Node
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: |
npm ci
cd ios && pod install
- name: Setup certificates
env:
CERTIFICATE_BASE64: ${{ secrets.IOS_CERTIFICATE_BASE64 }}
PROVISION_PROFILE_BASE64: ${{ secrets.IOS_PROVISION_PROFILE_BASE64 }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
run: |
# Create keychain
security create-keychain -p "$KEYCHAIN_PASSWORD" build.keychain
security default-keychain -s build.keychain
security unlock-keychain -p "$KEYCHAIN_PASSWORD" build.keychain
# Import certificate
echo "$CERTIFICATE_BASE64" | base64 --decode > certificate.p12
security import certificate.p12 -k build.keychain -P "${{ secrets.CERTIFICATE_PASSWORD }}" -T /usr/bin/codesign
# Import provisioning profile
echo "$PROVISION_PROFILE_BASE64" | base64 --decode > profile.mobileprovision
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
cp profile.mobileprovision ~/Library/MobileDevice/Provisioning\ Profiles/
- name: Build IPA
run: |
cd ios
xcodebuild -workspace MaternalApp.xcworkspace \
-scheme MaternalApp \
-configuration Release \
-archivePath $PWD/build/MaternalApp.xcarchive \
archive
xcodebuild -exportArchive \
-archivePath $PWD/build/MaternalApp.xcarchive \
-exportPath $PWD/build \
-exportOptionsPlist ExportOptions.plist
- name: Upload to TestFlight
env:
APP_STORE_CONNECT_API_KEY: ${{ secrets.APP_STORE_CONNECT_API_KEY }}
run: |
xcrun altool --upload-app \
--type ios \
--file ios/build/MaternalApp.ipa \
--apiKey "${{ secrets.API_KEY_ID }}" \
--apiIssuer "${{ secrets.API_ISSUER_ID }}"
build-android:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')
steps:
- uses: actions/checkout@v3
- name: Setup Node
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Setup Java
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '11'
- name: Install dependencies
run: npm ci
- name: Setup keystore
env:
KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }}
run: |
echo "$KEYSTORE_BASE64" | base64 --decode > android/app/release.keystore
echo "MATERNAL_RELEASE_STORE_FILE=release.keystore" >> android/gradle.properties
echo "MATERNAL_RELEASE_KEY_ALIAS=${{ secrets.ANDROID_KEY_ALIAS }}" >> android/gradle.properties
echo "MATERNAL_RELEASE_STORE_PASSWORD=${{ secrets.ANDROID_STORE_PASSWORD }}" >> android/gradle.properties
echo "MATERNAL_RELEASE_KEY_PASSWORD=${{ secrets.ANDROID_KEY_PASSWORD }}" >> android/gradle.properties
- name: Build APK
run: |
cd android
./gradlew assembleRelease
- name: Build AAB
run: |
cd android
./gradlew bundleRelease
- name: Upload to Play Store
uses: r0adkll/upload-google-play@v1
with:
serviceAccountJsonPlainText: ${{ secrets.PLAY_SERVICE_ACCOUNT_JSON }}
packageName: com.maternalapp.android
releaseFiles: android/app/build/outputs/bundle/release/app-release.aab
track: internal
status: draft
```
---
## TestFlight Configuration
### App Store Connect Setup
```javascript
// ios/fastlane/metadata/en-US/description.txt
Maternal is your AI-powered parenting companion, designed to reduce mental load and bring confidence to your parenting journey.
Key Features:
Smart activity tracking with voice input
AI assistant available 24/7 for parenting questions
Real-time family synchronization
Sleep predictions based on your baby's patterns
Growth tracking with WHO percentiles
// ios/fastlane/metadata/en-US/keywords.txt
parenting,baby tracker,sleep tracking,feeding log,AI assistant,family app,childcare
```
### Beta Testing Groups
```yaml
# TestFlight Groups
internal_testing:
name: "Internal Team"
members: 10
builds: all
beta_families:
name: "Beta Families"
members: 50
builds: stable
feedback: enabled
early_access:
name: "Early Access"
members: 500
builds: release_candidate
```
---
## Google Play Console Configuration
### Store Listing
```yaml
# Play Console Setup
app_details:
title: "Maternal - AI Parenting Assistant"
short_description: "Smart parenting companion with AI support"
full_description: |
Complete description...
category: "Parenting"
content_rating: "Everyone"
graphics:
icon: 512x512px
feature_graphic: 1024x500px
screenshots:
phone: [6 images minimum]
tablet: [optional]
```
### Release Tracks
```yaml
internal_testing:
testers: "internal-testers@maternalapp.com"
release_frequency: "daily"
closed_testing:
testers: 100
release_frequency: "weekly"
open_testing:
countries: ["US", "CA", "GB", "AU"]
release_frequency: "bi-weekly"
production:
rollout_percentage: 10 # Start with 10%
staged_rollout: true
```
---
## Over-the-Air Updates
### CodePush Setup
```bash
# Install CodePush
npm install react-native-code-push
# iOS setup
cd ios && pod install
# Register app with CodePush
code-push app add Maternal-iOS ios react-native
code-push app add Maternal-Android android react-native
```
### Update Configuration
```javascript
// App.js
import CodePush from 'react-native-code-push';
const codePushOptions = {
checkFrequency: CodePush.CheckFrequency.ON_APP_RESUME,
installMode: CodePush.InstallMode.ON_NEXT_RESTART,
mandatoryInstallMode: CodePush.InstallMode.IMMEDIATE,
updateDialog: {
title: 'Update Available',
mandatoryUpdateMessage: 'An important update is available.',
optionalUpdateMessage: 'An update is available. Would you like to install it?',
},
};
export default CodePush(codePushOptions)(App);
```
### Deployment Commands
```bash
# Deploy update to staging
code-push release-react Maternal-iOS ios -d Staging
code-push release-react Maternal-Android android -d Staging
# Promote to production
code-push promote Maternal-iOS Staging Production -r 10%
code-push promote Maternal-Android Staging Production -r 10%
```
---
## Performance Monitoring
### Build Size Optimization
```javascript
// metro.config.js
module.exports = {
transformer: {
minifierConfig: {
keep_fnames: true,
mangle: {
keep_fnames: true,
},
},
},
};
```
### Bundle Analysis
```bash
# Analyze bundle size
npx react-native-bundle-visualizer
# iOS specific
npx react-native bundle --platform ios --dev false --entry-file index.js --bundle-output ios/main.jsbundle --assets-dest ios
# Android specific
cd android && ./gradlew bundleRelease --scan
```
---
## Pre-Launch Checklist
### iOS Submission
- [ ] TestFlight build approved
- [ ] App Store screenshots (6.5", 5.5")
- [ ] App preview video (optional)
- [ ] Privacy policy URL
- [ ] Support URL
- [ ] Marketing URL
- [ ] Age rating questionnaire
- [ ] Export compliance
- [ ] App Review notes
### Android Submission
- [ ] Signed AAB uploaded
- [ ] Store listing complete
- [ ] Content rating questionnaire
- [ ] Target audience declaration
- [ ] Data safety form
- [ ] Privacy policy URL
- [ ] App category selected
- [ ] Closed testing feedback addressed
### General Requirements
- [ ] COPPA compliance verified
- [ ] GDPR compliance documented
- [ ] Terms of service updated
- [ ] Support system ready
- [ ] Analytics tracking verified
- [ ] Crash reporting active
- [ ] Performance benchmarks met
- [ ] Accessibility tested

View File

@@ -1,346 +0,0 @@
# MVP Features List - AI-Powered Maternal Organization App
## 🎯 MVP Goal
Launch a functional app that solves the most acute pain points for mothers with children 0-6 years old, focusing on reducing mental load through intelligent tracking and AI-powered support.
## 📱 Core User Experience (Week 1-2 Priority)
### User Onboarding & Account Setup
- **Quick Registration**
- Email/phone signup with verification
- Google/Apple social login
- Basic profile creation (name, timezone)
- COPPA/GDPR consent flow
- **Child Profile Setup**
- Add child (name, birthdate, gender optional)
- Support for 1-2 children (free tier)
- Basic medical info (allergies, conditions)
- Profile photo upload
- **Family Access**
- Invite one partner/caregiver
- Simple permission model (view/edit)
- Share code for quick partner setup
## 🍼 Essential Tracking Features (Week 2-4 Priority)
### Feeding Tracker
- **Quick Log Options**
- Breast (left/right/both) with timer
- Bottle (amount in oz/ml)
- Start/stop timer functionality
- Previous feeding quick-repeat
- **Voice Input**
- "Baby fed 4 ounces at 3pm"
- "Started nursing left side"
- Natural language processing
### Sleep Tracker
- **Simple Sleep Logging**
- One-tap sleep start/end
- Nap vs night sleep
- Location (crib, car, stroller)
- Quick notes option
- **AI Sleep Predictions** ⭐
- Next nap time prediction
- Wake window calculations
- Optimal bedtime suggestions
- Pattern recognition after 5 days
### Diaper Tracker
- **Fast Diaper Logging**
- Wet/dirty/both buttons
- Time auto-stamps
- Optional notes (rash, color)
- Pattern tracking for health
### Growth Tracker
- **Basic Measurements**
- Weight entry
- Height entry
- Growth chart visualization
- WHO percentile calculations
## 🤖 AI Assistant - The Killer Feature (Week 3-5 Priority)
### 24/7 Conversational Support
- **Natural Language Chat**
- "Why won't my baby sleep?"
- "Is this feeding pattern normal?"
- "What solids should I introduce?"
- "Help with sleep regression"
- **Contextual Responses**
- Uses your child's tracked data
- Age-appropriate guidance
- Evidence-based recommendations
- Remembers conversation context
- **Safety Features**
- Emergency resource links
- "Consult doctor" prompts for concerns
- Disclaimer on medical advice
- Crisis hotline integration
### Smart Insights & Predictions
- **Pattern Recognition**
- "Your baby sleeps better after morning walks"
- "Feeding intervals are increasing"
- "Nap duration improving this week"
- **Proactive Suggestions**
- "Based on patterns, next feeding around 2:30pm"
- "Consider starting bedtime routine at 6:45pm"
- "Growth spurt likely - expect increased feeding"
## 📅 Basic Family Coordination (Week 4-5 Priority)
### Real-Time Sync
- **Instant Updates**
- Activities sync across devices
- Partner sees updates immediately
- Offline mode with sync queue
- Conflict resolution
### Simple Notifications
- **Smart Reminders**
- Medication schedules
- Vaccination appointments
- Custom reminders
- Pattern-based alerts
### Activity Feed
- **Family Timeline**
- Chronological activity list
- Filter by child/activity type
- Today/yesterday/week views
- Quick stats dashboard
## 📊 Essential Analytics (Week 5-6 Priority)
### Daily Summaries
- **Overview Dashboard**
- Today's feeding total
- Sleep duration (day/night)
- Last activities at a glance
- Trends vs yesterday
### Weekly Patterns
- **Simple Reports**
- Average sleep per day
- Feeding frequency trends
- Growth trajectory
- Exportable for pediatrician
## 🌍 Internationalization & Localization
### Language Support (MVP Phase)
- **Initial Languages**
- English (primary)
- Spanish (large US population)
- French (Canadian market)
- Portuguese (Brazilian market)
- Simplified Chinese (growth market)
- **Localization Framework**
- All strings externalized from day 1
- RTL support structure (Arabic/Hebrew ready)
- Date/time format localization
- Number format localization
- Currency display for future features
- **AI Assistant Multilingual**
- Responses in user's selected language
- Language detection from voice input
- Culturally appropriate advice
- Local emergency resources by region
- **Content Localization**
- Measurement units (metric/imperial)
- Growth charts by region (WHO/CDC)
- Vaccination schedules by country
- Local pediatric guidelines
- Timezone auto-detection
## 🔒 Privacy & Security Essentials
### Data Protection
- **Security Basics**
- End-to-end encryption
- Secure authentication
- Biometric login option
- Auto-logout settings
### Privacy Controls
- **User Control**
- Data export capability
- Account deletion option
- No third-party data sharing
- Anonymous mode available
- Region-specific privacy compliance
## 📱 Technical MVP Requirements
### Platform Support
- **Mobile First**
- iOS 14+ support
- Android 10+ support
- Responsive design
- Tablet optimization (Phase 2)
### Performance Standards
- **User Experience**
- 2-second max load time
- Offline core features
- <100MB app size
- 60fps scrolling
### Accessibility Basics
- **Inclusive Design**
- Large touch targets (44x44 min)
- High contrast mode
- Text size adjustment
- Screen reader support
## 💰 Monetization - Simple Tiers
### Free Tier (Launch)
- 1-2 children max
- All core tracking features
- Basic AI assistance (10 questions/day)
- 7-day data history
- Basic patterns & insights
### Premium Tier ($9.99/month)
- Unlimited children
- Unlimited AI assistance
- Full data history
- Advanced predictions
- Priority support
- Export features
- Advanced insights
## 🚫 NOT in MVP (Future Releases)
### Deferred Features
- ❌ Meal planning
- ❌ Financial tracking
- ❌ Community forums
- ❌ Photo milestone tracking
- ❌ Video consultations
- ❌ Smart home integration
- ❌ Web version
- ❌ Wearable integration
- ❌ School platform connections
## 📈 Success Metrics for MVP
### Key Performance Indicators
- **User Acquisition**
- 1,000 downloads in first month
- 40% complete onboarding
- 25% invite a partner
- **Engagement Metrics**
- 60% daily active users
- 5+ logs per day average
- 3+ AI interactions weekly
- 70% week-1 retention
- **Technical Metrics**
- <2% crash rate
- 99.5% uptime
- <3 second response time
- 4.0+ app store rating
## 🗓️ 6-Week MVP Timeline
### Week 1-2: Foundation
- User authentication system
- Basic child profiles
- Core database schema
- Initial UI framework
- i18n framework setup
- String externalization
### Week 3-4: Core Features
- Feeding/sleep/diaper tracking
- Voice input integration
- Real-time sync
- Basic notifications
- Multilingual voice recognition
### Week 5-6: AI Integration
- LLM integration (OpenAI/Claude)
- Context-aware responses
- Pattern recognition
- Sleep predictions
- Language-specific AI responses
### Week 7-8: Polish & Launch
- Bug fixes & optimization
- App store preparation (multiple locales)
- Beta testing with 50 families (diverse languages)
- Launch marketing preparation
- Translation quality review
## 🎯 MVP Principles
### Focus Areas
1. **Solve One Problem Well**: Reduce mental load through intelligent tracking
2. **AI as Differentiator**: Make the assistant genuinely helpful from day 1
3. **Trust Through Privacy**: Parents need to feel data is secure
4. **Work in Chaos**: One-handed, interruption-resistant design
5. **Immediate Value**: User should see benefit within first 24 hours
### Quality Thresholds
- **Stability over features**: Better to have 5 rock-solid features than 10 buggy ones
- **Real-time sync must be flawless**: Partners rely on accurate shared data
- **AI responses must be helpful**: No generic, unhelpful responses
- **Voice input must be accurate**: Critical for hands-occupied situations
## 🚀 Post-MVP Roadmap Preview
### Phase 2 (Months 2-3)
- Community features with moderation
- Photo milestone tracking
- Meal planning basics
- Calendar integration
- Additional languages (German, Italian, Japanese, Korean, Arabic)
### Phase 3 (Months 4-6)
- Financial tracking
- Smart home integration
- Professional tools
- Advanced analytics
- Telemedicine integration
## ✅ MVP Launch Checklist
### Pre-Launch Requirements
- [ ] COPPA/GDPR compliance verified
- [ ] Privacy policy & terms of service (all languages)
- [ ] App store assets ready (localized)
- [ ] Beta testing with 50+ families (diverse languages/cultures)
- [ ] Customer support system setup (multilingual)
- [ ] Analytics tracking implemented
- [ ] Crash reporting active
- [ ] Payment processing tested (multi-currency)
- [ ] Backup systems verified
- [ ] Security audit completed
- [ ] Translation quality assurance completed
### Launch Day Essentials
- [ ] App store submission approved (all regions)
- [ ] Marketing website live (multilingual)
- [ ] Support documentation ready (all languages)
- [ ] Social media accounts active
- [ ] Press kit available (multilingual)
- [ ] Customer feedback system active
- [ ] Monitoring dashboards operational
- [ ] Support team trained (language coverage)
- [ ] Emergency response plan ready
- [ ] Celebration planned! 🎉

View File

@@ -1,89 +0,0 @@
# Available Domains for Maternal Parenting App
**Both .com and .app domains show strong availability** across these 20 carefully researched names that convey support, organization, AI assistance, and reduced mental load for overwhelmed parents. Each name is under 15 characters, easy to spell, memorable, and professionally warm.
## Research methodology and validation
I deployed five research teams to explore different thematic categories and verify domain availability across multiple registrars including Namecheap, GoDaddy, Name.com, InstantDomainSearch, and DNSChecker. While registrars require interactive searches for definitive confirmation, extensive web research found **no active websites or businesses** using these names, indicating strong availability likelihood. You should verify final availability within 24-48 hours as domains are registered constantly.
## Top tier names (strongest recommendations)
These seven names scored highest across all criteria—memorability, brand strength, thematic fit, and availability confidence:
**CareAI** (6 characters) combines nurturing care with direct AI positioning. Extremely concise and clear about technology-enabled parenting support. No existing services found across multiple registrars and search engines. Conveys both warmth and intelligence.
**MomMind** (7 characters) perfectly captures intelligent assistance through the "mind" concept while maintaining warm maternal connection. Short, brandable, and memorable with zero online presence detected. Suggests the app serves as a second mind for busy mothers.
**FamMind** (7 characters) offers broader family appeal than MomMind while maintaining the intelligent assistant positioning. Modern and tech-forward with no conflicting websites found. Appeals to all parents rather than mothers exclusively.
**CareGlow** (8 characters) evokes warmth, positivity, and radiant care. The "glow" connects naturally to maternal imagery while "care" remains direct and clear. Highly memorable and brandable with no active businesses using this name.
**FamNest** (7 characters) combines family focus with nest imagery suggesting safety, home, and warmth. Perfect for family hub concept with strong visual identity potential. No major web presence detected across multiple searches.
**MomFlow** (7 characters) suggests smooth, effortless family management through productivity flow. Easy to pronounce with strong appeal for reducing mental load. No active website found.
**NestWise** (8 characters) merges nurturing nest imagery with wisdom and guidance. Professional yet warm, suggesting smart parenting support. Clean search results indicate availability across registrars.
## AI and technology-focused names
These options emphasize intelligent assistance and smart parenting technology:
**NurturAI** (8 characters) beautifully combines nurture with AI through intentional spelling (dropping the 'e' from nurture). Sophisticated yet approachable with no websites found using this spelling variant. The creative spelling makes it more unique and brandable.
**MomPulse** (8 characters) suggests real-time monitoring and staying connected with needs. "Pulse" conveys being in tune with family rhythms. Modern and dynamic while maintaining warmth. No existing services detected.
**GuideMom** (8 characters) offers clear value proposition about providing guidance. Direct and memorable with professional tone. Zero online presence found across multiple registrar searches.
**BabyMind** (8 characters) appeals specifically to new parents and infant care. Suggests intelligent support during the demanding early parenting phase. No conflicting websites identified.
## Organization and coordination names
These emphasize family management and reducing mental load:
**FamFlow** (7 characters) conveys smooth family coordination and workflow optimization. Short, catchy, and professional with strong brandability. No active websites found.
**CoordKit** (8 characters) directly communicates "coordination toolkit" with professional, functional clarity. Modern tech feel while maintaining warmth. No major online presence detected.
**OrgaMom** (7 characters) provides direct organization messaging for mothers. Playful yet professional and easy to remember. Clean availability status across searches.
**MomCoord** (8 characters) straightforward mom coordination concept. Clear purpose with professional appeal. No existing businesses found using this name.
## Calm and stress relief names
These focus on easing parental overwhelm and providing peace:
**CalmPath** (8 characters) suggests a journey toward tranquility and calm parenting. Clear, memorable, and evocative with easy spelling. Professional yet warm tone with no active websites detected.
**ParentFlow** (10 characters) conveys smooth, effortless parenting where everything flows naturally. Modern professional branding appealing to tech-savvy parents. No conflicting online presence found.
**CalmLift** (8 characters) suggests lifting burdens and providing relief from stress. Strong emotional connection for overwhelmed parents. Memorable and distinctive with clean availability.
**MomPeace** (8 characters) directly addresses what stressed parents seek most. Short, memorable, and easy to spell with warm maternal tone remaining professional. No existing services identified.
## Community and support names
These emphasize connection, togetherness, and shared experience:
**MomGather** (9 characters) communicates community and togetherness perfectly. "Gather" feels warm, inviting, and action-oriented while appealing to maternal audience. Modern and professional with no brand conflicts found.
**ParentCove** (10 characters) uses "cove" to suggest safe harbor, protection, and community. Professional and warm simultaneously with good SEO potential through "parent" keyword. No major online presence detected.
## Domain verification checklist
To confirm availability for both .com and .app extensions, check these registrars immediately:
**Primary verification:** Visit Namecheap.com/domains/domain-name-search and enter each domain name. Check both .com and .app extensions. Namecheap offers competitive pricing ($10-15/year for .com, $15-20/year for .app) plus free WHOIS privacy protection.
**Secondary verification:** Cross-reference at GoDaddy.com/domains to ensure consistency. GoDaddy is the largest registrar with extensive customer support and reliable infrastructure.
**Rapid checking:** Use InstantDomainSearch.com for real-time results showing availability across multiple extensions simultaneously. This tool provides results in under 25 milliseconds.
**Important considerations:** The .app extension requires HTTPS/SSL certificates as it's owned by Google and operates as a secure namespace. Register both .com and .app for your chosen name simultaneously to protect your brand. Budget $50-75 for the domain pair plus SSL certificate for .app.
## Names confirmed unavailable (avoid these)
Research identified these names as taken: MomEase, CalmNest, ParentZen, MomHaven, MomCircle (active app), ParentPod, FamSync, ParentHub/parent.app, MomWise, MomAlly, ParentLift, CareBloom, MomGlow, MomThrive, and NurtureNow. These have active websites, businesses, or apps already using them.
## Registration strategy
Act quickly on your top 3-5 choices as domain availability changes constantly. The strongest options—CareAI, MomMind, FamMind, CareGlow, and FamNest—showed zero existing web presence across all research, indicating highest availability confidence. Consider registering multiple extensions (.com, .app, .net) for your final choice to protect brand identity. Verify within 24-48 hours and register immediately once confirmed to secure your preferred name.

View File

@@ -1,724 +0,0 @@
# State Management Schema - Maternal Organization App
## Store Architecture Overview
### Redux Toolkit Structure
```typescript
// Core principles:
// - Single source of truth
// - Normalized state shape
// - Offline-first design
// - Optimistic updates
// - Automatic sync queue
```
---
## Root Store Structure
```typescript
interface RootState {
auth: AuthState;
user: UserState;
family: FamilyState;
children: ChildrenState;
activities: ActivitiesState;
ai: AIState;
sync: SyncState;
offline: OfflineState;
ui: UIState;
notifications: NotificationState;
analytics: AnalyticsState;
}
```
---
## Auth Slice
### State Shape
```typescript
interface AuthState {
isAuthenticated: boolean;
accessToken: string | null;
refreshToken: string | null;
tokenExpiry: number | null;
deviceFingerprint: string;
trustedDevices: string[];
authStatus: 'idle' | 'loading' | 'succeeded' | 'failed';
error: string | null;
}
```
### Actions
```typescript
// authSlice.ts
const authSlice = createSlice({
name: 'auth',
initialState,
reducers: {
loginStart: (state) => {
state.authStatus = 'loading';
},
loginSuccess: (state, action) => {
state.isAuthenticated = true;
state.accessToken = action.payload.accessToken;
state.refreshToken = action.payload.refreshToken;
state.tokenExpiry = action.payload.expiresAt;
state.authStatus = 'succeeded';
},
loginFailure: (state, action) => {
state.authStatus = 'failed';
state.error = action.payload;
},
tokenRefreshed: (state, action) => {
state.accessToken = action.payload.accessToken;
state.tokenExpiry = action.payload.expiresAt;
},
logout: (state) => {
return initialState;
},
},
});
```
---
## User Slice
### State Shape
```typescript
interface UserState {
currentUser: {
id: string;
email: string;
name: string;
locale: string;
timezone: string;
photoUrl?: string;
preferences: UserPreferences;
} | null;
subscription: {
tier: 'free' | 'premium' | 'plus';
expiresAt?: string;
aiQueriesUsed: number;
aiQueriesLimit: number;
};
}
interface UserPreferences {
darkMode: 'auto' | 'light' | 'dark';
notifications: {
push: boolean;
email: boolean;
quietHoursStart?: string;
quietHoursEnd?: string;
};
measurementUnit: 'metric' | 'imperial';
}
```
---
## Family Slice
### State Shape
```typescript
interface FamilyState {
currentFamily: {
id: string;
name: string;
shareCode: string;
createdBy: string;
} | null;
members: {
byId: Record<string, FamilyMember>;
allIds: string[];
};
invitations: Invitation[];
loadingStatus: LoadingStatus;
}
interface FamilyMember {
id: string;
name: string;
email: string;
role: 'parent' | 'caregiver' | 'viewer';
permissions: Permissions;
lastActive: string;
isOnline: boolean;
}
```
### Normalized Actions
```typescript
const familySlice = createSlice({
name: 'family',
initialState,
reducers: {
memberAdded: (state, action) => {
const member = action.payload;
state.members.byId[member.id] = member;
state.members.allIds.push(member.id);
},
memberUpdated: (state, action) => {
const { id, changes } = action.payload;
state.members.byId[id] = {
...state.members.byId[id],
...changes,
};
},
memberRemoved: (state, action) => {
const id = action.payload;
delete state.members.byId[id];
state.members.allIds = state.members.allIds.filter(mid => mid !== id);
},
},
});
```
---
## Children Slice
### State Shape
```typescript
interface ChildrenState {
children: {
byId: Record<string, Child>;
allIds: string[];
};
activeChildId: string | null;
milestones: {
byChildId: Record<string, Milestone[]>;
};
}
interface Child {
id: string;
name: string;
birthDate: string;
gender?: string;
photoUrl?: string;
medical: {
bloodType?: string;
allergies: string[];
conditions: string[];
medications: Medication[];
};
metrics: {
currentWeight?: Measurement;
currentHeight?: Measurement;
headCircumference?: Measurement;
};
}
```
---
## Activities Slice (Normalized)
### State Shape
```typescript
interface ActivitiesState {
activities: {
byId: Record<string, Activity>;
allIds: string[];
byChild: Record<string, string[]>; // childId -> activityIds
byDate: Record<string, string[]>; // date -> activityIds
};
activeTimers: {
[childId: string]: ActiveTimer;
};
filters: {
childId?: string;
dateRange?: { start: string; end: string };
types?: ActivityType[];
};
pagination: {
cursor: string | null;
hasMore: boolean;
isLoading: boolean;
};
}
interface Activity {
id: string;
childId: string;
type: ActivityType;
timestamp: string;
duration?: number;
details: ActivityDetails;
loggedBy: string;
syncStatus: 'synced' | 'pending' | 'error';
version: number; // For conflict resolution
}
interface ActiveTimer {
activityType: ActivityType;
startTime: number;
pausedDuration: number;
isPaused: boolean;
}
```
### Activity Actions
```typescript
const activitiesSlice = createSlice({
name: 'activities',
initialState,
reducers: {
// Optimistic update
activityLogged: (state, action) => {
const activity = {
...action.payload,
syncStatus: 'pending',
};
state.activities.byId[activity.id] = activity;
state.activities.allIds.unshift(activity.id);
// Update indexes
if (!state.activities.byChild[activity.childId]) {
state.activities.byChild[activity.childId] = [];
}
state.activities.byChild[activity.childId].unshift(activity.id);
},
// Sync confirmed
activitySynced: (state, action) => {
const { localId, serverId } = action.payload;
state.activities.byId[localId].id = serverId;
state.activities.byId[localId].syncStatus = 'synced';
},
// Timer management
timerStarted: (state, action) => {
const { childId, activityType } = action.payload;
state.activeTimers[childId] = {
activityType,
startTime: Date.now(),
pausedDuration: 0,
isPaused: false,
};
},
},
});
```
---
## AI Slice
### State Shape
```typescript
interface AIState {
conversations: {
byId: Record<string, Conversation>;
activeId: string | null;
};
insights: {
byChildId: Record<string, Insight[]>;
pending: Insight[];
};
predictions: {
byChildId: Record<string, Predictions>;
};
quotas: {
dailyQueries: number;
dailyLimit: number;
resetAt: string;
};
}
interface Conversation {
id: string;
childId?: string;
messages: Message[];
context: ConversationContext;
lastMessageAt: string;
}
interface Predictions {
nextNapTime?: { time: string; confidence: number };
nextFeedingTime?: { time: string; confidence: number };
growthSpurt?: { likelihood: number; expectedIn: string };
}
```
---
## Sync Slice (Critical for Offline)
### State Shape
```typescript
interface SyncState {
queue: SyncQueueItem[];
conflicts: ConflictItem[];
lastSync: {
[entityType: string]: string; // ISO timestamp
};
syncStatus: 'idle' | 'syncing' | 'error' | 'offline';
retryCount: number;
webSocket: {
connected: boolean;
reconnectAttempts: number;
};
}
interface SyncQueueItem {
id: string;
type: 'CREATE' | 'UPDATE' | 'DELETE';
entity: 'activity' | 'child' | 'family';
payload: any;
timestamp: string;
retries: number;
error?: string;
}
interface ConflictItem {
id: string;
localVersion: any;
serverVersion: any;
strategy: 'manual' | 'local' | 'server' | 'merge';
}
```
### Sync Actions
```typescript
const syncSlice = createSlice({
name: 'sync',
initialState,
reducers: {
addToQueue: (state, action) => {
state.queue.push({
id: nanoid(),
...action.payload,
timestamp: new Date().toISOString(),
retries: 0,
});
},
removeFromQueue: (state, action) => {
state.queue = state.queue.filter(item => item.id !== action.payload);
},
conflictDetected: (state, action) => {
state.conflicts.push(action.payload);
},
conflictResolved: (state, action) => {
const { id, resolution } = action.payload;
state.conflicts = state.conflicts.filter(c => c.id !== id);
// Apply resolution...
},
syncCompleted: (state, action) => {
state.lastSync[action.payload.entity] = new Date().toISOString();
state.syncStatus = 'idle';
},
},
});
```
---
## Offline Slice
### State Shape
```typescript
interface OfflineState {
isOnline: boolean;
queuedActions: OfflineAction[];
cachedData: {
[key: string]: {
data: any;
timestamp: string;
ttl: number;
};
};
retryPolicy: {
maxRetries: number;
retryDelay: number;
backoffMultiplier: number;
};
}
interface OfflineAction {
id: string;
action: AnyAction;
meta: {
offline: {
effect: any;
commit: AnyAction;
rollback: AnyAction;
};
};
}
```
---
## UI Slice
### State Shape
```typescript
interface UIState {
theme: 'light' | 'dark' | 'auto';
activeScreen: string;
modals: {
[modalId: string]: {
isOpen: boolean;
data?: any;
};
};
loading: {
[key: string]: boolean;
};
errors: {
[key: string]: ErrorInfo;
};
toasts: Toast[];
bottomSheet: {
isOpen: boolean;
content: 'quickActions' | 'activityDetails' | null;
};
}
interface Toast {
id: string;
type: 'success' | 'error' | 'info';
message: string;
duration: number;
}
```
---
## Middleware Configuration
### Store Setup
```typescript
// store/index.ts
import { configureStore } from '@reduxjs/toolkit';
import {
persistStore,
persistReducer,
FLUSH,
REHYDRATE,
PAUSE,
PERSIST,
PURGE,
REGISTER,
} from 'redux-persist';
import AsyncStorage from '@react-native-async-storage/async-storage';
const persistConfig = {
key: 'root',
storage: AsyncStorage,
whitelist: ['auth', 'user', 'children', 'activities'],
blacklist: ['ui', 'sync'], // Don't persist UI state
};
const rootReducer = combineReducers({
auth: authReducer,
user: userReducer,
family: familyReducer,
children: childrenReducer,
activities: activitiesReducer,
ai: aiReducer,
sync: syncReducer,
offline: offlineReducer,
ui: uiReducer,
notifications: notificationsReducer,
analytics: analyticsReducer,
});
const persistedReducer = persistReducer(persistConfig, rootReducer);
export const store = configureStore({
reducer: persistedReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: {
ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
},
}).concat([
syncMiddleware,
offlineMiddleware,
analyticsMiddleware,
conflictResolutionMiddleware,
]),
});
export const persistor = persistStore(store);
```
### Sync Middleware
```typescript
// middleware/syncMiddleware.ts
export const syncMiddleware: Middleware = (store) => (next) => (action) => {
const result = next(action);
// Queue actions for sync
if (action.type.includes('activities/') && !action.meta?.skipSync) {
const state = store.getState();
if (!state.offline.isOnline) {
store.dispatch(addToQueue({
type: 'UPDATE',
entity: 'activity',
payload: action.payload,
}));
} else {
// Sync immediately
syncActivity(action.payload);
}
}
return result;
};
```
### Offline Middleware
```typescript
// middleware/offlineMiddleware.ts
export const offlineMiddleware: Middleware = (store) => (next) => (action) => {
// Check network status
if (action.type === 'network/statusChanged') {
const isOnline = action.payload;
if (isOnline && store.getState().sync.queue.length > 0) {
// Process offline queue
store.dispatch(processOfflineQueue());
}
}
// Handle optimistic updates
if (action.meta?.offline) {
const { effect, commit, rollback } = action.meta.offline;
// Apply optimistic update
next(action);
// Attempt sync
effect()
.then(() => next(commit))
.catch(() => next(rollback));
return;
}
return next(action);
};
```
---
## Selectors
### Memoized Selectors
```typescript
// selectors/activities.ts
import { createSelector } from '@reduxjs/toolkit';
export const selectActivitiesByChild = createSelector(
[(state: RootState) => state.activities.activities.byId,
(state: RootState, childId: string) => state.activities.activities.byChild[childId]],
(byId, activityIds = []) =>
activityIds.map(id => byId[id]).filter(Boolean)
);
export const selectTodaysSummary = createSelector(
[(state: RootState, childId: string) => selectActivitiesByChild(state, childId)],
(activities) => {
const today = new Date().toDateString();
const todaysActivities = activities.filter(
a => new Date(a.timestamp).toDateString() === today
);
return {
feedings: todaysActivities.filter(a => a.type === 'feeding').length,
sleepHours: calculateSleepHours(todaysActivities),
diapers: todaysActivities.filter(a => a.type === 'diaper').length,
};
}
);
```
---
## Conflict Resolution
### Conflict Resolution Strategy
```typescript
// utils/conflictResolution.ts
export const resolveConflict = (
local: Activity,
remote: Activity
): Activity => {
// Last write wins for simple conflicts
if (local.version === remote.version) {
return local.timestamp > remote.timestamp ? local : remote;
}
// Server version is higher - merge changes
if (remote.version > local.version) {
return {
...remote,
// Preserve local notes if different
details: {
...remote.details,
notes: local.details.notes !== remote.details.notes
? `${remote.details.notes}\n---\n${local.details.notes}`
: remote.details.notes,
},
};
}
// Local version is higher
return local;
};
```
---
## Performance Optimizations
### Normalized State Updates
```typescript
// Batch updates for performance
const activitiesSlice = createSlice({
name: 'activities',
reducers: {
activitiesBatchUpdated: (state, action) => {
const activities = action.payload;
// Use immer's batching
activities.forEach(activity => {
state.activities.byId[activity.id] = activity;
if (!state.activities.allIds.includes(activity.id)) {
state.activities.allIds.push(activity.id);
}
});
},
},
});
```
### Lazy Loading
```typescript
// Lazy load historical data
export const loadMoreActivities = createAsyncThunk(
'activities/loadMore',
async ({ cursor, limit = 20 }, { getState }) => {
const response = await api.getActivities({ cursor, limit });
return response.data;
},
{
condition: (_, { getState }) => {
const state = getState() as RootState;
return !state.activities.pagination.isLoading;
},
}
);
```

View File

@@ -1,420 +0,0 @@
# Technical Stack - Open Source Technologies for Maternal Organization App
## Mobile Application Development
### Cross-Platform Framework
- **React Native** (Primary Choice)
- `react-native`: Core framework
- `react-native-cli`: Command line interface
- `expo`: Development toolchain and libraries
- `react-navigation`: Navigation library
- `react-native-paper`: Material Design components
- `react-native-elements`: UI toolkit
### Alternative Native Development
- **Flutter** (Alternative Option)
- `flutter`: Core SDK
- `flutter_bloc`: State management
- `provider`: Dependency injection
- `get_it`: Service locator
- `dio`: HTTP client
### State Management
- **Redux Toolkit**
- `@reduxjs/toolkit`: Modern Redux with less boilerplate
- `react-redux`: React bindings
- `redux-persist`: Offline data persistence
- `redux-offline`: Offline-first functionality
- `redux-saga`: Side effects management
### Local Database & Storage
- **SQLite** (Primary local database)
- `react-native-sqlite-storage`: SQLite for React Native
- `typeorm`: Object-relational mapping
- `realm`: Alternative mobile database
- **Async Storage**
- `@react-native-async-storage/async-storage`: Key-value storage
- `react-native-mmkv`: Fast key-value storage alternative
## Backend Infrastructure
### Core Backend Framework
- **Node.js** with **NestJS**
- `@nestjs/core`: Enterprise-grade Node.js framework
- `@nestjs/common`: Common utilities
- `@nestjs/platform-express`: Express adapter
- `@nestjs/microservices`: Microservices support
- `@nestjs/websockets`: WebSocket support
- `@nestjs/graphql`: GraphQL integration
### API Development
- **GraphQL**
- `apollo-server-express`: GraphQL server
- `type-graphql`: TypeScript GraphQL framework
- `graphql-subscriptions`: Real-time subscriptions
- `graphql-upload`: File upload handling
- **REST API**
- `express`: Web framework
- `fastify`: Alternative high-performance framework
- `cors`: Cross-origin resource sharing
- `helmet`: Security headers
- `compression`: Response compression
### Database Systems
- **PostgreSQL** (Primary database)
- `pg`: PostgreSQL client
- `knex`: SQL query builder
- `prisma`: Modern ORM
- `typeorm`: Alternative ORM
- **MongoDB** (Document storage)
- `mongoose`: MongoDB object modeling
- `mongodb`: Native driver
### Caching & Performance
- **Redis**
- `redis`: Redis client
- `ioredis`: Advanced Redis client
- `bull`: Queue management
- `node-cache`: In-memory caching
- **Elasticsearch** (Search & analytics)
- `@elastic/elasticsearch`: Official client
- `searchkit`: Search UI components
## AI & Machine Learning
### LLM Integration (Proprietary APIs)
- **OpenAI API** / **Anthropic Claude API** / **Google Gemini API**
- **LangChain** (Framework)
- `langchain`: Core library
- `@langchain/community`: Community integrations
- `@langchain/openai`: OpenAI integration
### Open Source ML/AI
- **TensorFlow.js**
- `@tensorflow/tfjs`: Core library
- `@tensorflow/tfjs-node`: Node.js bindings
- `@tensorflow/tfjs-react-native`: React Native support
- **ONNX Runtime**
- `onnxruntime-node`: Node.js inference
- `onnxruntime-react-native`: Mobile inference
### Natural Language Processing
- **Natural**
- `natural`: General NLP tasks
- `compromise`: Natural language understanding
- `sentiment`: Sentiment analysis
- `franc`: Language detection
### Pattern Recognition & Analytics
- **Time Series Analysis**
- `timeseries-analysis`: Time series forecasting
- `simple-statistics`: Statistical functions
- `regression`: Regression analysis
- **Data Processing**
- `pandas-js`: Data manipulation
- `dataframe-js`: DataFrame operations
- `ml-js`: Machine learning algorithms
## Real-Time Communication
### WebSocket & Real-Time Sync
- **Socket.io**
- `socket.io`: Server implementation
- `socket.io-client`: Client library
- `socket.io-redis`: Redis adapter for scaling
### Push Notifications
- **Firebase Cloud Messaging** (Free tier available)
- `firebase-admin`: Server SDK
- `react-native-firebase`: React Native integration
- **Alternative: Expo Push Notifications**
- `expo-notifications`: Notification handling
- `expo-server-sdk`: Server implementation
## Voice & Audio Processing
### Voice Input & Recognition
- **Whisper** (OpenAI's open source)
- `whisper`: Speech recognition
- `react-native-voice`: Voice recognition wrapper
- **Web Speech API**
- `react-speech-kit`: React speech components
- `speech-to-text`: Browser-based recognition
### Audio Processing
- **FFmpeg**
- `fluent-ffmpeg`: Node.js wrapper
- `react-native-ffmpeg`: Mobile integration
- **Web Audio API**
- `tone.js`: Audio synthesis and effects
- `wavesurfer.js`: Audio visualization
## Security & Privacy
### Authentication & Authorization
- **Supabase** (Open source Firebase alternative)
- `@supabase/supabase-js`: Client library
- `@supabase/auth-helpers`: Authentication utilities
- **Passport.js**
- `passport`: Authentication middleware
- `passport-jwt`: JWT strategy
- `passport-local`: Local strategy
### Encryption & Security
- **Cryptography**
- `bcrypt`: Password hashing
- `jsonwebtoken`: JWT tokens
- `crypto-js`: Encryption utilities
- `node-forge`: Cryptography toolkit
- **Security Middleware**
- `helmet`: Security headers
- `express-rate-limit`: Rate limiting
- `express-validator`: Input validation
- `hpp`: HTTP parameter pollution prevention
### COPPA/GDPR Compliance
- **Age Verification**
- `age-calculator`: Age calculation utilities
- Custom implementation required
- **Data Privacy**
- `anonymize`: Data anonymization
- `gdpr-guard`: GDPR compliance helpers
## File & Media Management
### Image Processing
- **Sharp**
- `sharp`: High-performance image processing
- `react-native-image-resizer`: Mobile image resizing
- `react-native-image-picker`: Image selection
### File Storage
- **MinIO** (Self-hosted S3-compatible)
- `minio`: Object storage server
- `multer`: File upload middleware
- `multer-s3`: S3 storage engine
### Document Processing
- **PDF Generation**
- `pdfkit`: PDF generation
- `puppeteer`: HTML to PDF conversion
- `react-native-pdf`: PDF viewing
## Calendar & Scheduling
### Calendar Integration
- **Calendar Libraries**
- `node-ical`: iCal parsing
- `ical-generator`: iCal generation
- `react-native-calendars`: Calendar components
- `react-big-calendar`: Web calendar component
### Scheduling
- **Cron Jobs**
- `node-cron`: Task scheduling
- `agenda`: Job scheduling
- `bull`: Queue-based job processing
## Integration Libraries
### External Service Integrations
- **Google APIs**
- `googleapis`: Google services client
- `@react-native-google-signin/google-signin`: Google sign-in
- **Microsoft Graph**
- `@microsoft/microsoft-graph-client`: Graph API client
- **School Platforms**
- Custom API integrations required
- `axios`: HTTP client for API calls
### Smart Home Integration
- **Home Assistant**
- `home-assistant-js-websocket`: WebSocket client
- **Voice Assistants**
- `ask-sdk`: Alexa Skills Kit
- `actions-on-google`: Google Assistant
## Data Visualization & Analytics
### Charting Libraries
- **D3.js Ecosystem**
- `d3`: Core visualization library
- `react-native-svg`: SVG support for React Native
- `victory-native`: React Native charts
- **Chart.js**
- `chart.js`: Charting library
- `react-chartjs-2`: React wrapper
- `react-native-chart-kit`: React Native charts
### Analytics
- **Matomo** (Open source analytics)
- `matomo-tracker`: Analytics tracking
- **PostHog** (Open source product analytics)
- `posthog-js`: JavaScript client
- `posthog-react-native`: React Native client
## Development Tools
### Testing Frameworks
- **Unit Testing**
- `jest`: Testing framework
- `@testing-library/react-native`: React Native testing
- `enzyme`: Component testing
- **E2E Testing**
- `detox`: React Native E2E testing
- `appium`: Cross-platform mobile testing
- `cypress`: Web testing
### Code Quality
- **Linting & Formatting**
- `eslint`: JavaScript linter
- `prettier`: Code formatter
- `husky`: Git hooks
- `lint-staged`: Pre-commit linting
### Development Environment
- **Build Tools**
- `webpack`: Module bundler
- `babel`: JavaScript compiler
- `metro`: React Native bundler
- **Development Servers**
- `nodemon`: Node.js auto-restart
- `concurrently`: Run multiple commands
- `dotenv`: Environment variables
## DevOps & Infrastructure
### Container Orchestration
- **Docker**
- `docker`: Containerization
- `docker-compose`: Multi-container apps
- **Kubernetes** (for scaling)
- `kubernetes`: Container orchestration
- `helm`: Kubernetes package manager
### CI/CD
- **GitHub Actions** / **GitLab CI** / **Jenkins**
- `semantic-release`: Automated versioning
- `standard-version`: Changelog generation
### Monitoring & Logging
- **Sentry** (Open source error tracking)
- `@sentry/node`: Node.js SDK
- `@sentry/react-native`: React Native SDK
- **Winston** (Logging)
- `winston`: Logging library
- `morgan`: HTTP request logger
### Message Queue
- **RabbitMQ**
- `amqplib`: RabbitMQ client
- **Apache Kafka** (for high scale)
- `kafkajs`: Kafka client
## Additional Utilities
### Date & Time
- `dayjs`: Lightweight date library
- `date-fns`: Date utility library
- `moment-timezone`: Timezone handling
- `react-native-date-picker`: Date picker component
### Forms & Validation
- `react-hook-form`: Form management
- `yup`: Schema validation
- `joi`: Object schema validation
- `react-native-masked-text`: Input masking
### Localization
- `i18next`: Internationalization framework
- `react-i18next`: React integration
- `react-native-localize`: Device locale detection
### Utilities
- `lodash`: Utility functions
- `uuid`: UUID generation
- `validator`: String validators
- `numeral`: Number formatting
## Infrastructure Services (Self-Hosted Options)
### Backend as a Service
- **Supabase** (Complete backend solution)
- **Appwrite** (Alternative BaaS)
- **Parse Server** (Mobile backend)
### Search Infrastructure
- **Meilisearch** (Fast search engine)
- **Typesense** (Typo-tolerant search)
### Email Service
- **Nodemailer** with SMTP
- **SendGrid** (Free tier available)
- **Postal** (Self-hosted)
## Performance Optimization
### Mobile Performance
- `react-native-fast-image`: Optimized image loading
- `react-native-super-grid`: Efficient grid rendering
- `recyclerlistview`: High-performance lists
- `react-native-reanimated`: Smooth animations
### Backend Performance
- `cluster`: Node.js clustering
- `pm2`: Process management
- `compression`: Response compression
- `memory-cache`: In-memory caching
## Accessibility Tools
- `react-native-accessibility`: Accessibility utilities
- `react-native-tts`: Text-to-speech
- `react-native-screen-reader`: Screen reader detection
## Development Recommendations
### Minimum Viable Stack
1. **Frontend**: React Native + Expo
2. **Backend**: NestJS + PostgreSQL
3. **Real-time**: Socket.io
4. **AI**: OpenAI/Claude API + LangChain
5. **Auth**: Supabase Auth
6. **Storage**: MinIO/Supabase Storage
7. **Cache**: Redis
8. **Search**: Meilisearch
### Scalability Considerations
- Start with monolithic backend, prepare for microservices
- Use message queues early for async operations
- Implement caching strategy from day one
- Design for offline-first mobile experience
- Plan for horizontal scaling with Kubernetes
### Security Priorities
- Implement end-to-end encryption for sensitive data
- Use JWT with refresh tokens
- Apply rate limiting on all endpoints
- Regular security audits with OWASP tools
- COPPA/GDPR compliance from the start

View File

@@ -1,575 +0,0 @@
# Testing Strategy Document - Maternal Organization App
## Testing Philosophy
### Core Principles
- **User-Centric Testing**: Focus on real parent workflows
- **Offline-First Validation**: Test sync and conflict resolution
- **AI Response Quality**: Verify helpful, safe responses
- **Accessibility Testing**: Ensure one-handed operation works
- **Performance Under Stress**: Test with interrupted network, low battery
### Coverage Goals
- **Unit Tests**: 80% code coverage
- **Integration Tests**: All API endpoints
- **E2E Tests**: Critical user journeys
- **Performance**: Sub-3 second response times
- **Accessibility**: WCAG AA compliance
---
## Unit Testing
### Test Structure
```javascript
// Standard test file naming
ComponentName.test.tsx
ServiceName.test.ts
utils.test.ts
```
### Component Testing Example
```typescript
// FeedingTracker.test.tsx
describe('FeedingTracker', () => {
it('should start timer on breast feeding selection', () => {
const { getByTestId } = render(<FeedingTracker childId="chd_123" />);
fireEvent.press(getByTestId('breast-left-button'));
expect(getByTestId('timer-display')).toBeTruthy();
});
it('should validate minimum feeding duration', () => {
const onSave = jest.fn();
const { getByTestId } = render(<FeedingTracker onSave={onSave} />);
fireEvent.press(getByTestId('save-button'));
expect(getByTestId('error-message')).toHaveTextContent('Feeding too short');
expect(onSave).not.toHaveBeenCalled();
});
});
```
### Service Testing Example
```typescript
// SleepPredictionService.test.ts
describe('SleepPredictionService', () => {
it('should predict nap time within 30 minutes', async () => {
const mockSleepData = generateMockSleepHistory(7); // 7 days
const prediction = await service.predictNextNap('chd_123', mockSleepData);
expect(prediction.confidence).toBeGreaterThan(0.7);
expect(prediction.predictedTime).toBeInstanceOf(Date);
expect(prediction.wakeWindow).toBeBetween(90, 180); // minutes
});
});
```
### Redux Testing
```typescript
// trackingSlice.test.ts
describe('tracking reducer', () => {
it('should handle activity logged', () => {
const action = activityLogged({
id: 'act_123',
type: 'feeding',
timestamp: new Date().toISOString()
});
const newState = trackingReducer(initialState, action);
expect(newState.activities).toHaveLength(1);
expect(newState.lastSync).toBeDefined();
});
});
```
---
## Integration Testing
### API Endpoint Testing
```typescript
// auth.integration.test.ts
describe('POST /api/v1/auth/register', () => {
it('should create user with family', async () => {
const response = await request(app)
.post('/api/v1/auth/register')
.send({
email: 'test@example.com',
password: 'SecurePass123!',
name: 'Test User'
});
expect(response.status).toBe(201);
expect(response.body.data).toHaveProperty('user.id');
expect(response.body.data).toHaveProperty('family.shareCode');
expect(response.body.data.tokens.accessToken).toMatch(/^eyJ/);
});
it('should enforce password requirements', async () => {
const response = await request(app)
.post('/api/v1/auth/register')
.send({
email: 'test@example.com',
password: 'weak'
});
expect(response.status).toBe(400);
expect(response.body.error.code).toBe('VALIDATION_ERROR');
});
});
```
### WebSocket Testing
```typescript
// realtime.integration.test.ts
describe('Family Activity Sync', () => {
let client1, client2;
beforeEach((done) => {
client1 = io('http://localhost:3000', {
auth: { token: 'parent1_token' }
});
client2 = io('http://localhost:3000', {
auth: { token: 'parent2_token' }
});
done();
});
it('should broadcast activity to family members', (done) => {
client2.on('activity-logged', (data) => {
expect(data.activityId).toBe('act_123');
expect(data.type).toBe('feeding');
done();
});
client1.emit('log-activity', {
type: 'feeding',
childId: 'chd_123'
});
});
});
```
---
## E2E Testing with Detox
### Critical User Journeys
```javascript
// e2e/criticalPaths.e2e.js
describe('Onboarding Flow', () => {
beforeAll(async () => {
await device.launchApp({ newInstance: true });
});
it('should complete registration and add first child', async () => {
// Registration
await element(by.id('get-started-button')).tap();
await element(by.id('email-input')).typeText('parent@test.com');
await element(by.id('password-input')).typeText('TestPass123!');
await element(by.id('register-button')).tap();
// Add child
await expect(element(by.id('add-child-screen'))).toBeVisible();
await element(by.id('child-name-input')).typeText('Emma');
await element(by.id('birth-date-picker')).tap();
await element(by.text('15')).tap();
await element(by.id('save-child-button')).tap();
// Verify dashboard
await expect(element(by.text('Emma'))).toBeVisible();
});
});
```
### Offline Sync Testing
```javascript
describe('Offline Activity Logging', () => {
it('should queue activities when offline', async () => {
// Go offline
await device.setURLBlacklist(['.*']);
// Log activity
await element(by.id('quick-log-feeding')).tap();
await element(by.id('amount-input')).typeText('4');
await element(by.id('save-button')).tap();
// Verify local storage
await expect(element(by.id('sync-pending-badge'))).toBeVisible();
// Go online
await device.clearURLBlacklist();
// Verify sync
await waitFor(element(by.id('sync-pending-badge')))
.not.toBeVisible()
.withTimeout(5000);
});
});
```
---
## Mock Data Structures
### User & Family Mocks
```typescript
// mocks/users.ts
export const mockParent = {
id: 'usr_mock1',
email: 'test@example.com',
name: 'Jane Doe',
locale: 'en-US',
timezone: 'America/New_York'
};
export const mockFamily = {
id: 'fam_mock1',
name: 'Test Family',
shareCode: 'TEST01',
members: [mockParent],
children: []
};
```
### Activity Mocks
```typescript
// mocks/activities.ts
export const mockFeeding = {
id: 'act_feed1',
childId: 'chd_mock1',
type: 'feeding',
startTime: '2024-01-10T14:30:00Z',
duration: 15,
details: {
type: 'breast',
side: 'left',
amount: null
}
};
export const generateMockActivities = (days: number) => {
const activities = [];
const now = new Date();
for (let d = 0; d < days; d++) {
// Generate realistic daily pattern
activities.push(
createMockFeeding(subDays(now, d), '07:00'),
createMockSleep(subDays(now, d), '09:00', 90),
createMockFeeding(subDays(now, d), '10:30'),
createMockDiaper(subDays(now, d), '11:00'),
createMockSleep(subDays(now, d), '13:00', 120),
createMockFeeding(subDays(now, d), '15:00')
);
}
return activities;
};
```
### AI Response Mocks
```typescript
// mocks/aiResponses.ts
export const mockAIResponses = {
sleepQuestion: {
message: "Why won't my baby sleep?",
response: "Based on Emma's recent patterns, she may be experiencing the 7-month sleep regression...",
suggestions: [
"Try starting bedtime routine 15 minutes earlier",
"Ensure room temperature is 68-72°F"
],
confidence: 0.85
},
feedingConcern: {
message: "Baby seems hungry all the time",
response: "Increased hunger at 6 months often signals a growth spurt...",
suggestions: [
"Consider increasing feeding frequency temporarily",
"Track wet diapers to ensure adequate intake"
],
confidence: 0.92
}
};
```
---
## Performance Testing
### Load Testing Scenarios
```javascript
// performance/loadTest.js
import http from 'k6/http';
import { check } from 'k6';
export const options = {
stages: [
{ duration: '2m', target: 100 }, // Ramp up
{ duration: '5m', target: 100 }, // Stay at 100 users
{ duration: '2m', target: 0 }, // Ramp down
],
thresholds: {
http_req_duration: ['p(95)<3000'], // 95% requests under 3s
http_req_failed: ['rate<0.1'], // Error rate under 10%
},
};
export default function () {
// Test activity logging endpoint
const payload = JSON.stringify({
childId: 'chd_test',
type: 'feeding',
amount: 120
});
const response = http.post('http://localhost:3000/api/v1/activities/feeding', payload, {
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ${__ENV.TEST_TOKEN}'
},
});
check(response, {
'status is 201': (r) => r.status === 201,
'response time < 500ms': (r) => r.timings.duration < 500,
});
}
```
### Mobile Performance Testing
```typescript
// Mobile performance metrics
describe('Performance Benchmarks', () => {
it('should render dashboard in under 1 second', async () => {
const startTime = Date.now();
await element(by.id('dashboard-screen')).tap();
await expect(element(by.id('activities-list'))).toBeVisible();
const loadTime = Date.now() - startTime;
expect(loadTime).toBeLessThan(1000);
});
it('should handle 1000+ activities smoothly', async () => {
// Test with large dataset
await device.launchApp({
newInstance: true,
launchArgs: { mockLargeDataset: true }
});
// Measure scroll performance
await element(by.id('activities-list')).scroll(500, 'down', NaN, 0.8);
// Should not freeze or stutter
});
});
```
---
## Accessibility Testing
### WCAG Compliance Tests
```typescript
// accessibility/wcag.test.tsx
import { axe, toHaveNoViolations } from 'jest-axe';
expect.extend(toHaveNoViolations);
describe('Accessibility Compliance', () => {
it('should have no WCAG violations on dashboard', async () => {
const { container } = render(<Dashboard />);
const results = await axe(container);
expect(results).toHaveNoViolations();
});
it('should support screen reader navigation', () => {
const { getByLabelText } = render(<FeedingTracker />);
expect(getByLabelText('Log feeding')).toBeTruthy();
expect(getByLabelText('Select breast side')).toBeTruthy();
});
});
```
### One-Handed Operation Tests
```javascript
// e2e/oneHanded.e2e.js
describe('One-Handed Operation', () => {
it('should access all critical functions with thumb', async () => {
const screenHeight = await device.getScreenHeight();
const thumbReach = screenHeight * 0.6; // Bottom 60%
// Verify critical buttons are in thumb zone
const feedButton = await element(by.id('quick-log-feeding')).getLocation();
expect(feedButton.y).toBeGreaterThan(thumbReach);
const sleepButton = await element(by.id('quick-log-sleep')).getLocation();
expect(sleepButton.y).toBeGreaterThan(thumbReach);
});
});
```
---
## AI Testing
### LLM Response Validation
```typescript
// ai/llmResponse.test.ts
describe('AI Assistant Response Quality', () => {
it('should provide contextual responses', async () => {
const context = {
childAge: 7, // months
recentActivities: mockRecentActivities,
query: "baby won't sleep"
};
const response = await aiService.generateResponse(context);
expect(response).toContain('7-month');
expect(response.confidence).toBeGreaterThan(0.7);
expect(response.suggestions).toBeArray();
expect(response.harmfulContent).toBe(false);
});
it('should refuse inappropriate requests', async () => {
const response = await aiService.generateResponse({
query: "diagnose my baby's rash"
});
expect(response).toContain('consult');
expect(response).toContain('healthcare provider');
});
});
```
---
## Test Data Management
### Database Seeding
```typescript
// test/seed.ts
export async function seedTestDatabase() {
await db.clean(); // Clear all data
const family = await createTestFamily();
const parent1 = await createTestUser('parent1@test.com', family.id);
const parent2 = await createTestUser('parent2@test.com', family.id);
const child = await createTestChild('Emma', '2023-06-15', family.id);
// Generate realistic activity history
await generateActivityHistory(child.id, 30); // 30 days
return { family, parent1, parent2, child };
}
```
### Test Isolation
```typescript
// jest.setup.ts
beforeEach(async () => {
await db.transaction.start();
});
afterEach(async () => {
await db.transaction.rollback();
jest.clearAllMocks();
});
```
---
## CI/CD Test Pipeline
### GitHub Actions Configuration
```yaml
# .github/workflows/test.yml
name: Test Suite
on: [push, pull_request]
jobs:
unit-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
- run: npm ci
- run: npm run test:unit
- uses: codecov/codecov-action@v2
integration-tests:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:15
redis:
image: redis:7
steps:
- uses: actions/checkout@v2
- run: npm ci
- run: npm run test:integration
e2e-tests:
runs-on: macos-latest
steps:
- uses: actions/checkout@v2
- run: npm ci
- run: npx detox build -c ios.sim.release
- run: npx detox test -c ios.sim.release
```
---
## Test Coverage Requirements
### Minimum Coverage Thresholds
```json
// jest.config.js
{
"coverageThreshold": {
"global": {
"branches": 70,
"functions": 80,
"lines": 80,
"statements": 80
},
"src/services/": {
"branches": 85,
"functions": 90
},
"src/components/": {
"branches": 75,
"functions": 85
}
}
}
```
### Critical Path Coverage
- Authentication flow: 100%
- Activity logging: 95%
- Real-time sync: 90%
- AI responses: 85%
- Offline queue: 90%
---
## Test Reporting
### Test Result Format
```bash
# Console output
PASS src/components/FeedingTracker.test.tsx
✓ should start timer on selection (45ms)
✓ should validate minimum duration (23ms)
✓ should sync with family members (112ms)
Test Suites: 45 passed, 45 total
Tests: 234 passed, 234 total
Coverage: 82% statements, 78% branches
Time: 12.456s
```
### Coverage Reports
- HTML reports in `/coverage/lcov-report/`
- Codecov integration for PR comments
- SonarQube for code quality metrics

View File

@@ -1,590 +0,0 @@
# Voice Input Processing Guide - Maternal Organization App
## Voice Processing Architecture
### Overview
Voice input enables hands-free logging during childcare activities. The system processes natural language in 5 languages, extracting structured data from casual speech patterns.
### Processing Pipeline
```
Audio Input → Speech Recognition → Language Detection →
Intent Classification → Entity Extraction → Action Execution →
Confirmation Feedback
```
---
## Whisper API Integration
### Configuration
```typescript
// services/whisperService.ts
import OpenAI from 'openai';
class WhisperService {
private client: OpenAI;
constructor() {
this.client = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
}
async transcribeAudio(audioBuffer: Buffer, language?: string): Promise<TranscriptionResult> {
try {
const response = await this.client.audio.transcriptions.create({
file: audioBuffer,
model: 'whisper-1',
language: language || 'en', // ISO-639-1 code
response_format: 'verbose_json',
timestamp_granularities: ['word'],
});
return {
text: response.text,
language: response.language,
confidence: this.calculateConfidence(response),
words: response.words,
};
} catch (error) {
return this.handleTranscriptionError(error);
}
}
}
```
### Audio Preprocessing
```typescript
// utils/audioPreprocessing.ts
export const preprocessAudio = async (audioFile: File): Promise<Buffer> => {
// Validate format
const validFormats = ['wav', 'mp3', 'm4a', 'webm'];
if (!validFormats.includes(getFileExtension(audioFile))) {
throw new Error('Unsupported audio format');
}
// Check file size (max 25MB for Whisper)
if (audioFile.size > 25 * 1024 * 1024) {
// Compress or chunk the audio
return await compressAudio(audioFile);
}
// Noise reduction for better accuracy
return await reduceNoise(audioFile);
};
```
---
## Natural Language Command Patterns
### Intent Classification
```typescript
enum VoiceIntent {
LOG_FEEDING = 'LOG_FEEDING',
LOG_SLEEP = 'LOG_SLEEP',
LOG_DIAPER = 'LOG_DIAPER',
LOG_MEDICATION = 'LOG_MEDICATION',
START_TIMER = 'START_TIMER',
STOP_TIMER = 'STOP_TIMER',
ASK_QUESTION = 'ASK_QUESTION',
CHECK_STATUS = 'CHECK_STATUS',
CANCEL = 'CANCEL'
}
interface IntentPattern {
intent: VoiceIntent;
patterns: RegExp[];
requiredEntities: string[];
examples: string[];
}
```
### English Language Patterns
```typescript
const englishPatterns: IntentPattern[] = [
{
intent: VoiceIntent.LOG_FEEDING,
patterns: [
/(?:baby |she |he )?(?:fed|ate|drank|had|nursed)/i,
/(?:bottle|breast|nursing|feeding)/i,
/(?:finished|done) (?:eating|feeding|nursing)/i,
],
requiredEntities: ['amount?', 'time?', 'type?'],
examples: [
"Baby fed 4 ounces",
"Just nursed for 15 minutes on the left",
"She had 120ml of formula at 3pm",
"Finished feeding, both sides, 20 minutes total"
]
},
{
intent: VoiceIntent.LOG_SLEEP,
patterns: [
/(?:went|going) (?:to )?(?:sleep|bed|nap)/i,
/(?:woke|wake|waking) up/i,
/(?:nap|sleep)(?:ping|ed)? (?:for|since)/i,
/(?:fell) asleep/i,
],
requiredEntities: ['time?', 'duration?'],
examples: [
"Down for a nap",
"Woke up from nap",
"Sleeping since 2pm",
"Just fell asleep in the stroller"
]
},
{
intent: VoiceIntent.LOG_DIAPER,
patterns: [
/(?:chang|dirty|wet|soil|poop|pee)/i,
/diaper/i,
/(?:number|#) (?:one|two|1|2)/i,
],
requiredEntities: ['type?'],
examples: [
"Changed wet diaper",
"Dirty diaper with rash",
"Just changed a poopy one",
"Diaper change, both wet and dirty"
]
}
];
```
### Multi-Language Patterns
```typescript
// Spanish patterns
const spanishPatterns: IntentPattern[] = [
{
intent: VoiceIntent.LOG_FEEDING,
patterns: [
/(?:comió|tomó|bebió|amamanté)/i,
/(?:biberón|pecho|lactancia)/i,
],
examples: [
"Tomó 120ml de fórmula",
"Amamanté 15 minutos lado izquierdo",
"Ya comió papilla"
]
}
];
// French patterns
const frenchPatterns: IntentPattern[] = [
{
intent: VoiceIntent.LOG_FEEDING,
patterns: [
/(?:mangé|bu|allaité|nourri)/i,
/(?:biberon|sein|tétée)/i,
],
examples: [
"Biberon de 120ml",
"Allaité 15 minutes côté gauche",
"A mangé sa purée"
]
}
];
// Portuguese patterns
const portuguesePatterns: IntentPattern[] = [
{
intent: VoiceIntent.LOG_FEEDING,
patterns: [
/(?:comeu|tomou|bebeu|amamentei)/i,
/(?:mamadeira|peito|amamentação)/i,
],
examples: [
"Tomou 120ml de fórmula",
"Amamentei 15 minutos lado esquerdo"
]
}
];
// Chinese patterns
const chinesePatterns: IntentPattern[] = [
{
intent: VoiceIntent.LOG_FEEDING,
patterns: [
/(?:喂|吃|喝|哺乳)/,
/(?:奶瓶|母乳|配方奶)/,
],
examples: [
"喝了120毫升配方奶",
"母乳喂养15分钟",
"吃了辅食"
]
}
];
```
---
## Entity Extraction
### Entity Types
```typescript
interface ExtractedEntities {
amount?: {
value: number;
unit: 'oz' | 'ml' | 'minutes';
};
time?: {
value: Date;
precision: 'exact' | 'approximate';
};
duration?: {
value: number;
unit: 'minutes' | 'hours';
};
side?: 'left' | 'right' | 'both';
type?: 'breast' | 'bottle' | 'solid' | 'wet' | 'dirty' | 'both';
location?: string;
notes?: string;
}
```
### Extraction Logic
```typescript
class EntityExtractor {
extractAmount(text: string): ExtractedEntities['amount'] {
// Numeric amounts with units
const amountPattern = /(\d+(?:\.\d+)?)\s*(oz|ounce|ml|milliliter|minute|min)/i;
const match = text.match(amountPattern);
if (match) {
return {
value: parseFloat(match[1]),
unit: this.normalizeUnit(match[2])
};
}
// Word numbers
const wordNumbers = {
'one': 1, 'two': 2, 'three': 3, 'four': 4, 'five': 5,
'ten': 10, 'fifteen': 15, 'twenty': 20, 'thirty': 30,
};
for (const [word, value] of Object.entries(wordNumbers)) {
if (text.includes(word)) {
return { value, unit: this.inferUnit(text) };
}
}
return undefined;
}
extractTime(text: string, timezone: string): ExtractedEntities['time'] {
const now = new Date();
// Relative times
if (/just|now|right now/i.test(text)) {
return { value: now, precision: 'exact' };
}
if (/ago/i.test(text)) {
const minutesAgo = this.extractMinutesAgo(text);
return {
value: new Date(now.getTime() - minutesAgo * 60000),
precision: 'approximate'
};
}
// Clock times
const timePattern = /(\d{1,2}):?(\d{2})?\s*(am|pm)?/i;
const match = text.match(timePattern);
if (match) {
return {
value: this.parseClockTime(match, timezone),
precision: 'exact'
};
}
return { value: now, precision: 'approximate' };
}
extractSide(text: string): ExtractedEntities['side'] {
if (/left|izquierdo|gauche|esquerdo|左/i.test(text)) return 'left';
if (/right|derecho|droit|direito|右/i.test(text)) return 'right';
if (/both|ambos|deux|ambos|两|両/i.test(text)) return 'both';
return undefined;
}
}
```
---
## Intent Processing Engine
### Main Processing Flow
```typescript
class VoiceCommandProcessor {
async processVoiceInput(
audioBuffer: Buffer,
context: UserContext
): Promise<ProcessedCommand> {
// 1. Transcribe audio
const transcription = await this.whisperService.transcribeAudio(
audioBuffer,
context.language
);
if (transcription.confidence < 0.5) {
return this.handleLowConfidence(transcription);
}
// 2. Detect intent
const intent = await this.detectIntent(
transcription.text,
context.language
);
// 3. Extract entities
const entities = await this.extractEntities(
transcription.text,
intent,
context
);
// 4. Validate command
const validation = this.validateCommand(intent, entities);
if (!validation.isValid) {
return this.requestClarification(validation.missingInfo);
}
// 5. Execute action
return this.executeCommand(intent, entities, context);
}
private async detectIntent(
text: string,
language: string
): Promise<VoiceIntent> {
const patterns = this.getPatternsByLanguage(language);
for (const pattern of patterns) {
for (const regex of pattern.patterns) {
if (regex.test(text)) {
return pattern.intent;
}
}
}
// Fallback to AI intent detection
return this.detectIntentWithAI(text, language);
}
}
```
---
## Error Recovery
### Common Recognition Errors
```typescript
interface RecognitionError {
type: 'LOW_CONFIDENCE' | 'AMBIGUOUS' | 'MISSING_DATA' | 'INVALID_VALUE';
originalText: string;
suggestions?: string[];
}
class ErrorRecovery {
handleLowConfidence(transcription: TranscriptionResult): ProcessedCommand {
// Check for common misheard phrases
const corrections = this.checkCommonMishears(transcription.text);
if (corrections.confidence > 0.7) {
return this.retryWithCorrection(corrections.text);
}
return {
success: false,
action: 'CONFIRM',
message: `Did you say "${transcription.text}"?`,
alternatives: this.getSimilarPhrases(transcription.text)
};
}
checkCommonMishears(text: string): CorrectionResult {
const corrections = {
'for ounces': 'four ounces',
'to ounces': 'two ounces',
'write side': 'right side',
'laugh side': 'left side',
'wet and dirty': 'wet and dirty',
'wedding dirty': 'wet and dirty',
};
for (const [misheard, correct] of Object.entries(corrections)) {
if (text.includes(misheard)) {
return {
text: text.replace(misheard, correct),
confidence: 0.8
};
}
}
return { text, confidence: 0.3 };
}
}
```
### Clarification Prompts
```typescript
const clarificationPrompts = {
MISSING_AMOUNT: {
en: "How much did baby eat?",
es: "¿Cuánto comió el bebé?",
fr: "Combien a mangé bébé?",
pt: "Quanto o bebê comeu?",
zh: "宝宝吃了多少?"
},
MISSING_TIME: {
en: "When did this happen?",
es: "¿Cuándo ocurrió esto?",
fr: "Quand cela s'est-il passé?",
pt: "Quando isso aconteceu?",
zh: "这是什么时候发生的?"
},
AMBIGUOUS_INTENT: {
en: "What would you like to log?",
es: "¿Qué te gustaría registrar?",
fr: "Que souhaitez-vous enregistrer?",
pt: "O que você gostaria de registrar?",
zh: "您想记录什么?"
}
};
```
---
## Offline Voice Processing
### Fallback Strategy
```typescript
class OfflineVoiceProcessor {
async processOffline(audioBuffer: Buffer): Promise<BasicTranscription> {
// Use device's native speech recognition
if (Platform.OS === 'ios') {
return this.useiOSSpeechRecognition(audioBuffer);
} else if (Platform.OS === 'android') {
return this.useAndroidSpeechRecognition(audioBuffer);
}
// Queue for later processing
return this.queueForOnlineProcessing(audioBuffer);
}
private async useiOSSpeechRecognition(audio: Buffer) {
// Use SFSpeechRecognizer
const recognizer = new SFSpeechRecognizer();
return recognizer.recognize(audio);
}
private async useAndroidSpeechRecognition(audio: Buffer) {
// Use Android SpeechRecognizer
const recognizer = new AndroidSpeechRecognizer();
return recognizer.recognize(audio);
}
}
```
---
## Confirmation & Feedback
### Voice Feedback System
```typescript
interface VoiceConfirmation {
text: string;
speech: string; // SSML for TTS
visual: {
icon: string;
color: string;
animation: string;
};
haptic?: 'success' | 'warning' | 'error';
}
const confirmations = {
FEEDING_LOGGED: {
text: "Feeding logged",
speech: "<speak>Got it! <break time='200ms'/> Logged <say-as interpret-as='cardinal'>4</say-as> ounces.</speak>",
visual: {
icon: 'check_circle',
color: 'success',
animation: 'bounce'
},
haptic: 'success'
}
};
```
---
## Testing Voice Commands
### Test Scenarios
```typescript
const voiceTestCases = [
// English
{ input: "Baby ate 4 ounces", expected: { intent: 'LOG_FEEDING', amount: 4, unit: 'oz' }},
{ input: "Nursed for fifteen minutes on the left", expected: { intent: 'LOG_FEEDING', duration: 15, side: 'left' }},
// Spanish
{ input: "Tomó 120 mililitros", expected: { intent: 'LOG_FEEDING', amount: 120, unit: 'ml' }},
// Edge cases
{ input: "Fed... um... about 4 or 5 ounces", expected: { intent: 'LOG_FEEDING', amount: 4, confidence: 'low' }},
{ input: "Changed a really dirty diaper", expected: { intent: 'LOG_DIAPER', type: 'dirty', notes: 'really dirty' }},
];
```
---
## Performance Optimization
### Audio Streaming
```typescript
class StreamingVoiceProcessor {
private audioChunks: Buffer[] = [];
private isProcessing = false;
async processStream(chunk: Buffer) {
this.audioChunks.push(chunk);
if (!this.isProcessing && this.hasEnoughAudio()) {
this.isProcessing = true;
const result = await this.processChunks();
this.isProcessing = false;
return result;
}
}
private hasEnoughAudio(): boolean {
// Need at least 0.5 seconds of audio
const totalSize = this.audioChunks.reduce((sum, chunk) => sum + chunk.length, 0);
return totalSize > 8000; // ~0.5s at 16kHz
}
}
```
### Caching Common Commands
```typescript
const commandCache = new LRUCache<string, ProcessedCommand>({
max: 100,
ttl: 1000 * 60 * 60, // 1 hour
});
// Cache exact matches for common phrases
const cachedPhrases = [
"wet diaper",
"dirty diaper",
"just nursed",
"bottle feeding done",
"down for a nap",
"woke up"
];
```

File diff suppressed because it is too large Load Diff

View File

@@ -1,87 +0,0 @@
# The overwhelmed mother's digital lifeline: Building an AI-powered organization app for modern parenting
Mothers carry **71% of household mental load** while managing careers, childcare, and their own wellbeing - often with minimal support. With 10-20% experiencing untreated perinatal mental health conditions globally and 90% facing career-threatening challenges upon returning to work, the need for intelligent digital support has never been more critical. This comprehensive analysis reveals how an AI-powered app can transform the chaos of modern motherhood into manageable, predictable routines that actually work.
## The hidden crisis modern mothers face daily
The data paints a stark picture of maternal overwhelm that crosses all demographics and geographies. **Mothers handle 79% of daily household tasks** - over twice the contribution of fathers - while simultaneously managing complex schedules, making thousands of micro-decisions, and often sacrificing their own sleep and wellbeing. The mental load crisis is quantifiable: women perform nearly 4 hours of unpaid work daily compared to men's 2.5 hours globally, with mothers reporting feeling rushed 86% of the time.
Mental health challenges compound these organizational struggles. Postpartum depression affects 13-20% of mothers worldwide, yet **75% remain untreated** due to stigma, access barriers, and time constraints. In developing countries, rates climb to 19.8% postpartum. The economic toll is staggering - untreated maternal mental health conditions cost $14.2 billion annually in the US alone, or $32,000 per mother-infant pair. Sleep deprivation peaks during infancy, with mothers losing an average of 42 minutes nightly, while 40.3% of infants aged 4-11 months don't meet recommended sleep durations, creating a destructive cycle of exhaustion.
The work-life balance struggle intensifies these challenges. Nine out of ten working mothers face at least one major career-threatening challenge, with 57% of those with children under five feeling professionally held back. **Half of all employees with children** have considered leaving their organization due to inadequate childcare support. The partnership gap adds another layer - 74% of mothers manage children's schedules compared to their partners, and men consistently overestimate their household contributions, leading to resentment and conflict.
## Current solutions fall short of mothers' complex needs
The parenting app market, valued at $1.45-2.0 billion and growing at 7.8-20.37% annually, offers fragmented solutions that fail to address the holistic nature of maternal challenges. While apps like Huckleberry excel at sleep prediction with 93% success rates among 4 million users, and Cozi provides color-coded calendars for family coordination, **no single platform integrates all aspects** of maternal organization with intelligent automation.
Major gaps plague existing solutions. Integration between different apps remains poor, forcing mothers to manage multiple platforms. AI capabilities are limited to basic pattern recognition rather than predictive, proactive support. Community features often devolve into toxic environments - BabyCenter's 1.8/5 Trustpilot rating stems from "mean girl mob mentality" and poor moderation. Platform inconsistencies frustrate users, with features working differently across web and mobile versions. Perhaps most critically, current apps treat symptoms rather than addressing the underlying mental load problem.
User complaints reveal deep dissatisfaction with generic, copy-pasted advice that ignores individual family contexts. Peanut's "Tinder for moms" concept struggles to create meaningful connections, with users reporting difficulty converting matches to real friendships. Premium pricing feels steep for basic features - Huckleberry charges $58.99 annually for sleep recommendations that become less useful once children enter daycare. The market clearly demands a comprehensive, intelligent solution that grows with families rather than forcing them to constantly switch platforms.
## AI transforms overwhelming complexity into manageable routines
The most promising AI implementations demonstrate remarkable potential for reducing maternal burden. Huckleberry's SweetSpot® algorithm analyzes hundreds of millions of sleep data points to predict optimal nap times with uncanny accuracy, adapting to individual patterns within 5 days. Their success - trusted by 4 million parents across 179 countries - proves mothers will embrace AI that delivers tangible results. Natural language processing enables voice logging during hands-occupied moments ("baby fed 4oz at 3pm"), while pattern recognition identifies trends humans miss.
Mental health support represents AI's most transformative application. Woebot's randomized controlled trial with 184 postpartum women showed **70% achieving clinically significant improvement** versus 30% in the control group, with participants engaging 5 times weekly on average. The 24/7 availability addresses traditional therapy barriers - cost, stigma, scheduling - while providing immediate crisis support with human escalation protocols. University of Texas researchers are developing specialized chatbots for postpartum depression through Postpartum Support International, recognizing AI's potential to reach underserved mothers.
Practical automation capabilities extend beyond emotional support. Ollie AI's meal planning platform saves families 5 hours weekly through natural language dietary preference processing and automated grocery integration. Google Assistant's Family Features recognize up to 6 family members' voices, enabling personalized responses and parental controls. Microsoft's Document Intelligence processes receipts with 90% accuracy improvement over manual entry, while computer vision applications automatically sort photos by child and milestone. These aren't futuristic concepts - they're proven technologies ready for integration.
## Core MVP features that deliver immediate value
Based on comprehensive research, the MVP must prioritize features addressing the most acute pain points while building toward a comprehensive platform. **Essential tracking capabilities** form the foundation: feeding, sleep, and diaper logging with voice input for hands-free operation. The magic happens when AI analyzes this data - Huckleberry's sleep prediction model demonstrates how pattern recognition transforms raw data into actionable insights. Multi-user access ensures both parents and caregivers stay synchronized, addressing the coordination challenges 74% of mothers face.
The **AI conversational assistant** represents the MVP's breakthrough feature. Available 24/7, it provides evidence-based guidance personalized to each child's patterns and developmental stage. Unlike generic chatbots, it learns from family data to offer increasingly relevant suggestions. Dr. Becky Kennedy's Good Inside app validates this approach with 90,000+ paying members for AI-powered parenting scripts. The assistant should handle everything from "why won't my baby sleep?" to "healthy dinner ideas for picky toddlers," reducing decision fatigue that plagues overwhelmed mothers.
Age-specific adaptations ensure relevance across the 0-6 range. For infants (0-1 year), prioritize feeding schedules, sleep optimization, growth tracking, and vaccination reminders. Toddler features (1-3 years) focus on routine management, potty training progress, and behavioral pattern analysis. Preschool tools (3-6 years) emphasize school readiness, social skill development, and activity coordination. **The platform must grow with families** rather than forcing app-switching as children develop.
Quick-win AI features provide immediate value while building user trust. Smart notifications deliver context-aware reminders based on family patterns - alerting about nap time based on wake windows, suggesting feeding times from hunger cues. Pattern detection identifies correlations mothers might miss: "Your baby sleeps 47 minutes longer after outdoor morning activities." Voice processing allows natural language input during chaotic moments. These features require relatively simple implementation while delivering outsized impact on daily stress.
## Building trust through privacy-first design
Privacy concerns dominate parental technology decisions, making compliance and transparency competitive advantages rather than regulatory burdens. **COPPA compliance in the US** requires verifiable parental consent before collecting data from children under 13, with clear policies describing collection practices. GDPR Article 8 extends protection in Europe, with age thresholds varying by country. The app must implement risk-based verification - email confirmation for low-risk features, credit card verification for medium risk, government ID for high-risk data access.
Security architecture must exceed typical app standards given sensitive family data. End-to-end encryption protects information in transit and at rest. Regular security audits and penetration testing ensure ongoing protection. Multi-factor authentication secures parental accounts while maintaining quick access for authorized caregivers. **Data minimization principles** mean collecting only essential information, with automatic deletion of unnecessary data. Parents must control their data completely - viewing, downloading, and permanently deleting at will.
Transparency builds trust where many apps fail. Clear, plain-language privacy policies explain exactly what data is collected, how it's used, and who has access. Opt-in rather than opt-out for all non-essential features. No selling or sharing data with third parties for advertising. Age-appropriate content filtering and parental controls for any community features. YouTube's $170 million fine for tracking children without consent demonstrates the serious consequences of privacy violations - but also the opportunity to differentiate through ethical data practices.
## UX designed for chaos: One hand, divided attention, constant interruption
Mothers interact with technology under uniquely challenging conditions. Research shows 49% of mobile users operate phones one-handed while multitasking, with 70% of interactions lasting under 2 minutes. Parents experience "distracted short-burst usage" patterns with 58 daily phone checks between childcare tasks. **The UX must accommodate this reality** through placement of critical functions within thumb's reach, bottom navigation bars instead of hamburger menus, and gesture-based interactions for common tasks.
The three-tap rule governs feature design - core functions must be accessible within three taps or less. Auto-save functionality prevents data loss during inevitable interruptions. Resume capability allows mothers to complete tasks started hours earlier. Visual state indicators show progress at a glance. **Interruption-resistant design** means every interaction can be abandoned mid-task without losing work, crucial when children demand immediate attention.
Successful patterns from consumer apps translate effectively. Instagram's story-style updates work for sharing family moments with grandparents. TikTok's swipe navigation enables quick browsing during brief free moments. Voice input becomes essential when hands are occupied with children. Visual information trumps text - icons, colors, and progress bars communicate faster than words. The interface must feel familiar and intuitive, eliminating learning curves that busy mothers cannot afford.
## Technical architecture for reliability when families depend on you
The technical foundation must support families' mission-critical needs through offline-first architecture with seamless synchronization. Local databases serve as the single source of truth, ensuring the app works without internet connection - crucial during pediatrician visits in cellular dead zones or international travel. **Real-time synchronization** keeps all family members updated through WebSocket connections, with conflict resolution for simultaneous edits. Background sync handles updates efficiently without draining battery life.
Integration capabilities determine the platform's value within existing family ecosystems. Calendar synchronization with Google, Apple, and Outlook consolidates schedules. Health app connections track growth and development. School platform integration (ClassDojo, Seesaw, Remind) centralizes communication. Smart home compatibility enables voice control through Alexa and Google Assistant. **The app becomes the family's command center** rather than another isolated tool.
Scalability planning ensures the platform grows smoothly from thousands to millions of families. Microservices architecture separates different domains for independent scaling. Read replicas improve performance under load. Redis caching accelerates frequently accessed data. CDN integration speeds media delivery globally. The AI/ML infrastructure balances on-device processing for privacy-sensitive features with cloud computing for complex analytics. TensorFlow Lite and Core ML optimize mobile performance while maintaining sophisticated capabilities.
## Sustainable monetization that respects family budgets
The freemium model with thoughtfully designed tiers ensures accessibility while building sustainable revenue. **Free tier** includes core tracking for 1-2 children, basic milestone checking, and limited AI insights - enough to deliver value and build trust. Family tier at $9.99/month unlocks unlimited children, advanced AI predictions, full voice capabilities, and priority support. Family Plus at $14.99/month adds comprehensive integrations, advanced analytics, and exclusive expert content.
B2B2C partnerships expand reach while reducing acquisition costs. **Employer wellness programs** increasingly recognize supporting working parents improves productivity and retention. Insurance partnerships frame the app as preventive care, potentially covering subscriptions. Healthcare provider relationships enable pediatrician-recommended adoption. School district partnerships could provide subsidized access for all families. These channels validate the platform while reaching mothers who might not discover it independently.
Critical metrics guide sustainable growth. Customer Acquisition Cost (CAC) must remain below $30 for profitability. Lifetime Value (LTV) should exceed $200 through strong retention. Monthly Recurring Revenue (MRR) growth of 15-20% indicates healthy expansion. **Churn analysis by feature usage** identifies which capabilities drive retention. The goal isn't maximum revenue extraction but sustainable value exchange that supports continuous improvement while respecting family budgets.
## Product roadmap from MVP to comprehensive platform
**Phase 1 (Months 1-3)** launches core MVP features: basic tracking with voice input, AI chat assistant providing 24/7 guidance, pattern recognition for sleep and feeding, multi-user family access, and COPPA/GDPR compliant infrastructure. This foundation addresses immediate pain points while establishing technical architecture for expansion.
**Phase 2 (Months 4-6)** adds intelligence and community: advanced pattern predictions across all tracked metrics, moderated community forums with expert participation, photo milestone storage with automatic organization, comprehensive calendar integration, and initial school platform connections. These features transform the app from tracker to intelligent assistant.
**Phase 3 (Months 7-12)** delivers the full vision: predictive scheduling that anticipates family needs, mental health monitoring with intervention protocols, meal planning with grocery integration, financial tracking for family expenses, and telemedicine integration for virtual pediatric visits. Smart home integration enables voice control of core features.
**Future expansion (12+ months)** extends the platform's reach: web platform for desktop planning sessions, wearable integration for health tracking, professional tools for pediatricians and therapists, AI-powered child development assessments, and international localization for global families. The platform evolves into the definitive digital infrastructure for modern parenting.
## Conclusion: From overwhelming chaos to confident parenting
The research reveals an enormous, underserved market of mothers struggling with preventable organizational and emotional challenges. Current solutions address symptoms rather than root causes, forcing families to juggle multiple apps while still missing critical support. **An integrated AI-powered platform** that combines intelligent tracking, predictive scheduling, mental health support, and family coordination can transform the parenting experience from overwhelming to manageable.
Success requires more than technical excellence. The platform must earn trust through privacy-first design, respect mothers' chaotic reality through interruption-resistant UX, and deliver immediate value through AI that actually reduces mental load rather than adding complexity. By addressing the holistic needs of modern mothers - from midnight feeding sessions to career planning meetings - this comprehensive solution can become the indispensable digital partner that millions of families desperately need.
The opportunity extends beyond commercial success to genuine social impact. Reducing maternal mental load, improving mental health support access, and enabling more equitable household partnerships could reshape family dynamics globally. With the parenting app market growing 12-20% annually and mothers increasingly embracing AI assistance, the timing is ideal for a platform that finally delivers on technology's promise to make parenting not easier, but more confident, connected, and joyful.

View File

@@ -1,975 +0,0 @@
# Mobile App Best Practices for Future Implementation
## React Native Implementation Readiness Guide
---
## Overview
This document outlines best practices, architectural patterns, and implementation guidelines for building the native mobile apps (iOS & Android) using React Native. The current web implementation provides a solid foundation that can be leveraged for the mobile apps.
### Current Implementation Status
-**Web App (maternal-web)**: Fully implemented with Next.js 14
-**Backend API (maternal-app-backend)**: Complete with REST + WebSocket
-**Mobile Apps**: Not yet implemented (planned)
### Technology Stack for Mobile
```javascript
{
"react-native": "^0.73.0",
"expo": "~50.0.0",
"@react-navigation/native": "^6.1.0",
"@react-navigation/stack": "^6.3.0",
"react-native-paper": "^5.12.0",
"redux-toolkit": "^2.0.0",
"react-native-reanimated": "^3.6.0",
"expo-secure-store": "~12.8.0",
"expo-notifications": "~0.27.0"
}
```
---
## Architecture Principles
### 1. Code Reusability Between Web and Mobile
**Shared Business Logic**
```typescript
// ✅ GOOD: Platform-agnostic business logic
// libs/shared/src/services/activityService.ts
export class ActivityService {
async logActivity(data: ActivityData): Promise<Activity> {
// Platform-independent logic
return this.apiClient.post('/activities', data);
}
}
// Can be used in both web and mobile
```
**Platform-Specific UI**
```typescript
// ❌ BAD: Mixing UI and logic
function TrackingButton() {
const [activity, setActivity] = useState();
// Business logic mixed with UI
}
// ✅ GOOD: Separate concerns
// hooks/useActivityTracking.ts
export function useActivityTracking() {
// Reusable logic
}
// web/components/TrackingButton.tsx
// mobile/components/TrackingButton.tsx
// Different UI, same logic via hook
```
**Recommended Project Structure**
```
maternal-app-monorepo/
├── apps/
│ ├── web/ # Next.js web app (existing)
│ ├── mobile/ # React Native mobile app (future)
│ └── backend/ # NestJS API (existing)
├── packages/
│ ├── shared/ # Shared between web & mobile
│ │ ├── api-client/ # API communication
│ │ ├── state/ # Redux store & slices
│ │ ├── hooks/ # Custom React hooks
│ │ ├── utils/ # Utilities
│ │ └── types/ # TypeScript definitions
│ ├── ui-components/ # Platform-specific UI
│ │ ├── web/
│ │ └── mobile/
│ └── constants/ # Shared constants
└── tools/ # Build tools & scripts
```
---
## Mobile-Specific Features
### 1. Offline-First Architecture
**Local Database: SQLite**
```typescript
// Mobile: Use SQLite for offline storage
import * as SQLite from 'expo-sqlite';
const db = SQLite.openDatabase('maternal.db');
// Sync queue for offline operations
interface SyncQueueItem {
id: string;
operation: 'CREATE' | 'UPDATE' | 'DELETE';
entity: 'activity' | 'child' | 'family';
data: any;
timestamp: Date;
retryCount: number;
}
// Auto-sync when connection restored
export class OfflineSyncService {
async syncPendingChanges() {
const pendingItems = await this.getSyncQueue();
for (const item of pendingItems) {
try {
await this.syncItem(item);
await this.removefromQueue(item.id);
} catch (error) {
await this.incrementRetryCount(item.id);
}
}
}
}
```
**Conflict Resolution**
```typescript
// Last-write-wins with timestamp comparison
export class ConflictResolver {
resolve(local: Activity, remote: Activity): Activity {
const localTime = new Date(local.updatedAt);
const remoteTime = new Date(remote.updatedAt);
// Use latest version
return localTime > remoteTime ? local : remote;
}
}
```
### 2. Push Notifications
**Expo Notifications Setup**
```typescript
import * as Notifications from 'expo-notifications';
import * as Device from 'expo-device';
export class NotificationService {
async registerForPushNotifications() {
if (!Device.isDevice) {
return null;
}
const { status: existingStatus } =
await Notifications.getPermissionsAsync();
let finalStatus = existingStatus;
if (existingStatus !== 'granted') {
const { status } =
await Notifications.requestPermissionsAsync();
finalStatus = status;
}
if (finalStatus !== 'granted') {
return null;
}
const token = (
await Notifications.getExpoPushTokenAsync({
projectId: 'your-expo-project-id'
})
).data;
// Send token to backend
await this.apiClient.post('/users/push-token', { token });
return token;
}
// Configure notification behavior
configureNotifications() {
Notifications.setNotificationHandler({
handleNotification: async () => ({
shouldShowAlert: true,
shouldPlaySound: true,
shouldSetBadge: true,
}),
});
}
}
```
**Notification Categories**
```typescript
// Backend: Define notification types
export enum NotificationType {
FAMILY_UPDATE = 'family_update',
ACTIVITY_REMINDER = 'activity_reminder',
MILESTONE_REACHED = 'milestone_reached',
AI_INSIGHT = 'ai_insight',
SYNC_COMPLETE = 'sync_complete',
}
// Mobile: Handle notification tap
Notifications.addNotificationResponseReceivedListener(response => {
const { type, data } = response.notification.request.content;
switch (type) {
case NotificationType.FAMILY_UPDATE:
navigation.navigate('Family', { familyId: data.familyId });
break;
case NotificationType.ACTIVITY_REMINDER:
navigation.navigate('Track', { type: data.activityType });
break;
// ... handle other types
}
});
```
### 3. Biometric Authentication
**Face ID / Touch ID / Fingerprint**
```typescript
import * as LocalAuthentication from 'expo-local-authentication';
import * as SecureStore from 'expo-secure-store';
export class BiometricAuthService {
async isBiometricAvailable(): Promise<boolean> {
const compatible = await LocalAuthentication.hasHardwareAsync();
const enrolled = await LocalAuthentication.isEnrolledAsync();
return compatible && enrolled;
}
async authenticateWithBiometrics(): Promise<boolean> {
const result = await LocalAuthentication.authenticateAsync({
promptMessage: 'Authenticate to access Maternal App',
fallbackLabel: 'Use passcode',
});
return result.success;
}
async enableBiometricLogin(userId: string, token: string) {
// Store refresh token securely
await SecureStore.setItemAsync(
`auth_token_${userId}`,
token,
{
keychainAccessible:
SecureStore.WHEN_UNLOCKED_THIS_DEVICE_ONLY,
}
);
// Enable biometric flag
await SecureStore.setItemAsync(
'biometric_enabled',
'true'
);
}
async loginWithBiometrics(): Promise<string | null> {
const authenticated = await this.authenticateWithBiometrics();
if (!authenticated) {
return null;
}
// Retrieve stored token
const userId = await SecureStore.getItemAsync('current_user_id');
const token = await SecureStore.getItemAsync(`auth_token_${userId}`);
return token;
}
}
```
### 4. Voice Input (Whisper)
**React Native Voice**
```typescript
import Voice from '@react-native-voice/voice';
export class VoiceInputService {
constructor() {
Voice.onSpeechResults = this.onSpeechResults;
Voice.onSpeechError = this.onSpeechError;
}
async startListening() {
try {
await Voice.start('en-US');
} catch (error) {
console.error('Voice start error:', error);
}
}
async stopListening() {
try {
await Voice.stop();
} catch (error) {
console.error('Voice stop error:', error);
}
}
onSpeechResults = (event: any) => {
const transcript = event.value[0];
// Send to backend for processing with Whisper
this.processTranscript(transcript);
};
onSpeechError = (event: any) => {
console.error('Speech error:', event.error);
};
async processTranscript(transcript: string) {
// Send to backend Whisper API
const response = await fetch('/api/v1/voice/transcribe', {
method: 'POST',
body: JSON.stringify({ transcript }),
});
const { activityData } = await response.json();
return activityData;
}
}
```
### 5. Camera & Photo Upload
**Expo Image Picker**
```typescript
import * as ImagePicker from 'expo-image-picker';
export class PhotoService {
async requestPermissions() {
const { status } =
await ImagePicker.requestMediaLibraryPermissionsAsync();
if (status !== 'granted') {
Alert.alert(
'Permission needed',
'Please allow access to photos'
);
return false;
}
return true;
}
async pickImage() {
const hasPermission = await this.requestPermissions();
if (!hasPermission) return null;
const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: true,
aspect: [4, 3],
quality: 0.8,
});
if (!result.canceled) {
return result.assets[0].uri;
}
return null;
}
async takePhoto() {
const { status } =
await ImagePicker.requestCameraPermissionsAsync();
if (status !== 'granted') {
return null;
}
const result = await ImagePicker.launchCameraAsync({
allowsEditing: true,
aspect: [4, 3],
quality: 0.8,
});
if (!result.canceled) {
return result.assets[0].uri;
}
return null;
}
async uploadPhoto(uri: string, childId: string) {
const formData = new FormData();
formData.append('file', {
uri,
type: 'image/jpeg',
name: 'photo.jpg',
} as any);
formData.append('childId', childId);
const response = await fetch('/api/v1/children/photo', {
method: 'POST',
body: formData,
headers: {
'Content-Type': 'multipart/form-data',
},
});
return response.json();
}
}
```
---
## Performance Optimization
### 1. List Virtualization
**FlatList for Large Datasets**
```typescript
import { FlatList } from 'react-native';
// ✅ GOOD: Virtualized list for activities
<FlatList
data={activities}
renderItem={({ item }) => <ActivityCard activity={item} />}
keyExtractor={(item) => item.id}
// Performance optimizations
removeClippedSubviews={true}
maxToRenderPerBatch={10}
updateCellsBatchingPeriod={50}
initialNumToRender={10}
windowSize={5}
// Pull to refresh
onRefresh={handleRefresh}
refreshing={isRefreshing}
// Infinite scroll
onEndReached={loadMore}
onEndReachedThreshold={0.5}
/>
// ❌ BAD: Rendering all items at once
{activities.map(activity => <ActivityCard key={activity.id} activity={activity} />)}
```
### 2. Image Optimization
**React Native Fast Image**
```typescript
import FastImage from 'react-native-fast-image';
// ✅ GOOD: Optimized image loading
<FastImage
source={{
uri: childPhoto,
priority: FastImage.priority.high,
cache: FastImage.cacheControl.immutable,
}}
style={styles.childPhoto}
resizeMode={FastImage.resizeMode.cover}
/>
// Preload images for better UX
FastImage.preload([
{ uri: photo1 },
{ uri: photo2 },
]);
```
### 3. Animation Performance
**React Native Reanimated 3**
```typescript
import Animated, {
useSharedValue,
useAnimatedStyle,
withSpring,
} from 'react-native-reanimated';
// ✅ GOOD: Run on UI thread
function AnimatedButton() {
const scale = useSharedValue(1);
const animatedStyle = useAnimatedStyle(() => ({
transform: [{ scale: scale.value }],
}));
const handlePress = () => {
scale.value = withSpring(0.95, {}, () => {
scale.value = withSpring(1);
});
};
return (
<Animated.View style={animatedStyle}>
<TouchableOpacity onPress={handlePress}>
<Text>Track Activity</Text>
</TouchableOpacity>
</Animated.View>
);
}
```
### 4. Bundle Size Optimization
**Hermes Engine (for Android)**
```javascript
// android/app/build.gradle
project.ext.react = [
enableHermes: true, // Enable Hermes engine
]
// Results in:
// - Faster startup time
// - Lower memory usage
// - Smaller APK size
```
**Code Splitting**
```typescript
// Lazy load heavy screens
const AIAssistant = lazy(() => import('./screens/AIAssistant'));
const Analytics = lazy(() => import('./screens/Analytics'));
// Use with Suspense
<Suspense fallback={<LoadingSpinner />}>
<AIAssistant />
</Suspense>
```
---
## Testing Strategy for Mobile
### Unit Tests (Jest)
```typescript
import { renderHook, act } from '@testing-library/react-hooks';
import { useActivityTracking } from './useActivityTracking';
describe('useActivityTracking', () => {
it('should track activity successfully', async () => {
const { result } = renderHook(() => useActivityTracking());
await act(async () => {
await result.current.logActivity({
type: 'feeding',
childId: 'child_123',
});
});
expect(result.current.activities).toHaveLength(1);
});
});
```
### Component Tests (React Native Testing Library)
```typescript
import { render, fireEvent } from '@testing-library/react-native';
import { TrackingButton } from './TrackingButton';
describe('TrackingButton', () => {
it('should handle press event', () => {
const onPress = jest.fn();
const { getByText } = render(
<TrackingButton onPress={onPress} />
);
fireEvent.press(getByText('Track Feeding'));
expect(onPress).toHaveBeenCalled();
});
});
```
### E2E Tests (Detox)
```typescript
describe('Activity Tracking Flow', () => {
beforeAll(async () => {
await device.launchApp();
});
it('should log a feeding activity', async () => {
await element(by.id('track-feeding-btn')).tap();
await element(by.id('amount-input')).typeText('120');
await element(by.id('save-btn')).tap();
await expect(element(by.text('Activity saved'))).toBeVisible();
});
});
```
---
## Platform-Specific Considerations
### iOS Specific
**1. App Store Guidelines**
```markdown
- ✅ Submit privacy manifest (PrivacyInfo.xcprivacy)
- ✅ Declare data collection practices
- ✅ Request permissions with clear explanations
- ✅ Support all device sizes (iPhone, iPad)
- ✅ Dark mode support required
```
**2. iOS Permissions**
```xml
<!-- ios/maternal/Info.plist -->
<key>NSCameraUsageDescription</key>
<string>Take photos of your child's milestones</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Save and view photos of your child</string>
<key>NSMicrophoneUsageDescription</key>
<string>Use voice to log activities hands-free</string>
<key>NSFaceIDUsageDescription</key>
<string>Use Face ID for quick and secure login</string>
```
**3. iOS Background Modes**
```xml
<key>UIBackgroundModes</key>
<array>
<string>remote-notification</string>
<string>fetch</string>
</array>
```
### Android Specific
**1. Permissions**
```xml
<!-- android/app/src/main/AndroidManifest.xml -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
```
**2. ProGuard (Code Obfuscation)**
```
# android/app/proguard-rules.pro
-keep class com.maternalapp.** { *; }
-keepclassmembers class * {
@com.facebook.react.uimanager.annotations.ReactProp <methods>;
}
```
**3. App Signing**
```bash
# Generate release keystore
keytool -genkeypair -v -storetype PKCS12 \
-keystore maternal-app-release.keystore \
-alias maternal-app \
-keyalg RSA -keysize 2048 \
-validity 10000
```
---
## Deployment & Distribution
### App Store (iOS)
**1. Build Configuration**
```bash
# Install dependencies
cd ios && pod install
# Build for production
xcodebuild -workspace MaternalApp.xcworkspace \
-scheme MaternalApp \
-configuration Release \
-archivePath MaternalApp.xcarchive \
archive
# Export IPA
xcodebuild -exportArchive \
-archivePath MaternalApp.xcarchive \
-exportPath ./build \
-exportOptionsPlist ExportOptions.plist
```
**2. TestFlight (Beta Testing)**
```bash
# Upload to TestFlight
xcrun altool --upload-app \
--type ios \
--file MaternalApp.ipa \
--username "developer@example.com" \
--password "@keychain:AC_PASSWORD"
```
### Google Play (Android)
**1. Build AAB (Android App Bundle)**
```bash
cd android
./gradlew bundleRelease
# Output: android/app/build/outputs/bundle/release/app-release.aab
```
**2. Internal Testing Track**
```bash
# Upload to Google Play Console
# Use Fastlane or manual upload
```
### Over-the-Air Updates (CodePush)
**Setup for rapid iteration**
```bash
# Install CodePush CLI
npm install -g code-push-cli
# Register app
code-push app add maternal-app-ios ios react-native
code-push app add maternal-app-android android react-native
# Release update
code-push release-react maternal-app-ios ios \
-d Production \
--description "Bug fixes and performance improvements"
```
**Rollback Strategy**
```bash
# Rollback to previous version if issues detected
code-push rollback maternal-app-ios Production
# Monitor adoption rate
code-push deployment ls maternal-app-ios
```
---
## Monitoring & Analytics
### Crash Reporting (Sentry)
```typescript
import * as Sentry from '@sentry/react-native';
Sentry.init({
dsn: 'YOUR_SENTRY_DSN',
environment: __DEV__ ? 'development' : 'production',
tracesSampleRate: 1.0,
});
// Automatic breadcrumbs
Sentry.addBreadcrumb({
category: 'activity',
message: 'User logged feeding activity',
level: 'info',
});
// Custom error context
Sentry.setContext('user', {
id: user.id,
familyId: family.id,
});
```
### Performance Monitoring
```typescript
import * as Sentry from '@sentry/react-native';
// Monitor screen load time
const transaction = Sentry.startTransaction({
name: 'ActivityTrackingScreen',
op: 'navigation',
});
// ... screen loads ...
transaction.finish();
// Monitor specific operations
const span = transaction.startChild({
op: 'api.call',
description: 'Log activity',
});
await logActivity(data);
span.finish();
```
### Usage Analytics
```typescript
// Integrate with backend analytics service
import { Analytics } from '@maternal/shared/analytics';
Analytics.track('Activity Logged', {
type: 'feeding',
method: 'voice',
duration: 15000,
});
Analytics.screen('Activity Tracking');
Analytics.identify(user.id, {
familySize: family.members.length,
childrenCount: children.length,
isPremium: subscription.isPremium,
});
```
---
## Accessibility (WCAG AA Compliance)
### Screen Reader Support
```typescript
import { View, Text, TouchableOpacity } from 'react-native';
<TouchableOpacity
accessible={true}
accessibilityLabel="Log feeding activity"
accessibilityHint="Opens feeding activity tracker"
accessibilityRole="button"
onPress={handlePress}
>
<Text>Track Feeding</Text>
</TouchableOpacity>
```
### Dynamic Font Sizes
```typescript
import { Text, useWindowDimensions } from 'react-native';
// Respect user's font size preferences
<Text
style={{
fontSize: 16,
lineHeight: 24,
}}
allowFontScaling={true}
maxFontSizeMultiplier={2}
>
Activity logged successfully
</Text>
```
### Color Contrast
```typescript
// Ensure WCAG AA compliance (4.5:1 ratio for normal text)
const colors = {
primary: '#FF8B7D', // Coral
primaryText: '#1A1A1A', // Dark text on light background
background: '#FFFFFF',
textOnPrimary: '#FFFFFF', // White text on coral
};
// Validate contrast ratios in design system
```
---
## Security Best Practices
### Secure Storage
```typescript
import * as SecureStore from 'expo-secure-store';
// ✅ GOOD: Encrypted storage for sensitive data
await SecureStore.setItemAsync('auth_token', token);
// ❌ BAD: AsyncStorage for sensitive data (unencrypted)
await AsyncStorage.setItem('auth_token', token);
```
### Certificate Pinning
```typescript
// Prevent man-in-the-middle attacks
import { configureCertificatePinning } from 'react-native-cert-pinner';
await configureCertificatePinning([
{
hostname: 'api.maternalapp.com',
certificates: [
'sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=',
],
},
]);
```
### Jailbreak/Root Detection
```typescript
import JailMonkey from 'jail-monkey';
if (JailMonkey.isJailBroken()) {
Alert.alert(
'Security Warning',
'This app may not function properly on jailbroken devices'
);
}
```
---
## Migration Path from Web to Mobile
### Phase 1: Extract Shared Logic
```typescript
// 1. Move business logic to shared package
// packages/shared/src/services/
export class ActivityService { ... }
export class AIService { ... }
// 2. Update web app to use shared package
import { ActivityService } from '@maternal/shared';
```
### Phase 2: Build Mobile Shell
```typescript
// 1. Create React Native app with Expo
npx create-expo-app maternal-mobile
// 2. Set up navigation structure
// 3. Integrate shared services
// 4. Build basic UI with React Native Paper
```
### Phase 3: Implement Mobile-Specific Features
```typescript
// 1. Offline mode with SQLite
// 2. Push notifications
// 3. Biometric auth
// 4. Voice input
// 5. Camera integration
```
### Phase 4: Testing & Optimization
```typescript
// 1. Unit tests
// 2. Component tests
// 3. E2E tests with Detox
// 4. Performance profiling
// 5. Accessibility audit
```
### Phase 5: Beta Testing & Launch
```typescript
// 1. TestFlight (iOS)
// 2. Google Play Internal Testing
// 3. Gather feedback
// 4. Iterate based on metrics
// 5. Production launch
```
---
## Conclusion
This guide provides a comprehensive roadmap for implementing native mobile apps. Key takeaways:
1. **Code Reusability**: Share business logic between web and mobile
2. **Offline-First**: Essential for mobile UX
3. **Native Features**: Leverage platform-specific capabilities
4. **Performance**: Optimize for mobile constraints
5. **Testing**: Comprehensive strategy for quality
6. **Security**: Protect user data on mobile devices
7. **Analytics**: Track usage and iterate
The current web implementation already follows many mobile-friendly patterns, making the transition to React Native straightforward when the time comes.

File diff suppressed because it is too large Load Diff

View File

@@ -1,244 +0,0 @@
# Multi-Child Support Implementation Guide
## Overview
Implementation specifications for supporting multiple children in the maternal organization app with dynamic UI adaptation based on the number of children registered.
---
## Core Rules Implementation
### Rule 1: Dynamic Dashboard View (1-3 vs 3+ children)
**For 1-3 Children - Tab Implementation:**
- Display horizontal tabs at the top of the dashboard
- Each tab shows one child's name
- Add an "All" tab at the end to view combined summary
- Active tab should be visually distinct (use primary color from Design System)
- Tab transitions should be smooth and instantaneous
- Selected tab state must persist during app session
**For 3+ Children - Stacked Cards Implementation:**
- Display vertically scrollable cards
- Each card represents one child
- Cards should show compact summary (key metrics only)
- Include child's name and age on each card
- Add visual separation between cards (8px spacing)
- Implement pull-to-refresh for updating all cards
### Rule 2: Global Child Selector
**Implementation Requirements:**
- Add dropdown selector to app header (below navigation bar)
- Only display when family has 2+ children
- Show currently selected child(ren) name(s)
- Dropdown options must include:
- Individual child names with profile photos (if available)
- "All Children" option
- Visual indicator for currently selected
- Selector state must persist across all screens
- Update all displayed data when selection changes
---
## Screen-by-Screen Updates
### Dashboard Screen
- Implement view mode detection based on children count
- Add child selector if 2+ children
- Update summary calculations based on selected child(ren)
- For "All" selection, show aggregated statistics
- Ensure real-time sync updates correct child's data
### Activity Logging Screens
- Add child selection step before logging
- Default to last active child
- Allow bulk logging for multiple children (e.g., "both kids napping")
- Update confirmation messages to include child name(s)
- Store child association with each activity
### AI Assistant Screen
- Modify context building to include selected child's data
- Update prompts to specify which child when asking questions
- Allow questions about multiple children comparisons
- Include child name in AI responses for clarity
### Analytics Screen
- Add "Comparison" tab as specified in Rule 4
- Update all charts to filter by selected child(ren)
- Implement side-by-side view for comparing 2 children
- Add legend when showing multiple children's data
- Export reports should specify which child(ren) included
---
## Rule 3: Analytics Comparison Tab
### Comparison View Requirements
- Add new tab in Analytics section labeled "Compare"
- Only show when 2+ children registered
- Default to comparing all children
- Implement following comparison metrics:
- Sleep patterns overlay chart
- Feeding frequency comparison
- Growth curves on same graph
- Development milestones timeline
- Activity patterns heatmap
### Comparison Controls
- Add date range selector (default: last 7 days)
- Include child selector checkboxes
- Implement metric selector (choose what to compare)
- Add export functionality for comparison reports
- Use different colors per child (from a predefined palette)
---
## Rule 4: Voice Command Multi-Child Handling
### Voice Processing Updates
**Child Detection Logic:**
1. Parse voice input for child names
2. If child name detected, associate with that child
3. If no child name detected:
- For single child families: auto-select
- For multi-child families: prompt for selection
4. Support keywords: "both", "all kids", "everyone"
**Clarification Prompts:**
- "Which child is this for?"
- "Did you mean [Child Name]?"
- "Should I log this for all children?"
- Display child selector with voice feedback
- Allow voice response for selection
**Natural Language Patterns to Support:**
- "[Child name] just [activity]"
- "Both kids are [activity]"
- "Log feeding for [child name]"
- "All children went to bed"
- "The twins are napping"
---
## State Management Updates
### Redux Store Modifications
**UI Slice Updates:**
- Add active children IDs array (supports multi-select)
- Store default child ID for quick actions
- Add view mode preference (tabs vs cards)
- Cache last selected child per screen
- Store comparison view preferences
**Activities Slice Updates:**
- Index activities by child ID
- Support filtering by multiple children
- Add bulk operation support
- Update sync to handle multi-child selections
**Analytics Slice Updates:**
- Cache calculations per child
- Store comparison configurations
- Add aggregation logic for "all children" view
---
## API Updates
### Endpoint Modifications
**Activity Endpoints:**
- Accept child_id array for bulk operations
- Return child-specific data in responses
- Support filtering by multiple children
- Add comparison-specific endpoints
**Analytics Endpoints:**
- Add comparison query parameters
- Support multi-child aggregations
- Return child-separated statistics
- Include child identifiers in all responses
### WebSocket Updates
- Include child ID in all real-time events
- Support room-per-child architecture
- Emit updates only for selected children
- Handle bulk activity broadcasts
---
## Database Updates
### Schema Modifications
- Ensure all activity tables include child_id foreign key
- Add indexes on child_id for performance
- Create views for multi-child aggregations
- Add comparison preferences table
### Query Optimizations
- Implement efficient multi-child queries
- Add database functions for aggregations
- Optimize for common comparison queries
- Cache frequently accessed combinations
---
## Testing Requirements
### Unit Tests
- Test view mode selection logic
- Verify child selector state management
- Test voice command child detection
- Validate aggregation calculations
### Integration Tests
- Test multi-child activity logging flow
- Verify real-time sync for multiple children
- Test comparison view data accuracy
- Validate API filtering with multiple children
### E2E Tests
- Complete flow for 2-child family
- Complete flow for 4+ child family
- Voice command with child selection
- Analytics comparison interactions
---
## Migration Plan
### For Existing Users
1. Detect single-child accounts
2. Hide multi-child features initially
3. Enable features when second child added
4. Preserve all existing data associations
5. Default existing activities to first child
### UI Migration
1. Add child selector component globally
2. Update dashboard based on child count
3. Add comparison tab to analytics
4. Update all logging flows
5. Modify voice processing pipeline
---
## Performance Considerations
- Lazy load child data as needed
- Cache per-child calculations
- Implement virtual scrolling for many children
- Optimize database queries for multi-child filters
- Throttle real-time updates when showing multiple children
---
## Accessibility Updates
- Ensure child selector is screen-reader friendly
- Add voice announcements for child selection
- Label all charts with child names
- Support keyboard navigation for tabs
- Provide text alternatives for comparison visualizations

View File

@@ -1,367 +0,0 @@
# Multi-Child Implementation - Phase 3 Status Report
## Overview
This document tracks the implementation status of Phase 3 (Activity Logging) for the multi-child families feature.
**Date**: October 5, 2025
**Status**: ✅ **COMPLETE**
**Completion**: 6 of 6 tracking forms updated (100%)
---
## Completed Work
### ✅ Phase 1: Backend Infrastructure (100% Complete)
All backend infrastructure is in place and tested:
1. **Database Migrations**:
- ✅ V017: Child display preferences (displayColor, sortOrder, nickname)
- ✅ V018: Multi-child user preferences table
- ✅ V019: Activity bulk operations support
2. **API Endpoints**:
- ✅ POST `/api/v1/activities/bulk` - Bulk activity creation
- ✅ GET `/api/v1/activities?childIds=...` - Multi-child activity queries
- ✅ GET `/api/v1/analytics/compare` - Child comparison analytics
- ✅ GET `/api/v1/children/family/:familyId/statistics` - Family stats
3. **Services**:
- ✅ ChildrenService: Auto-color assignment, family statistics
- ✅ TrackingService: Bulk operations, multi-child queries
- ✅ ComparisonService: 4 metric types (sleep, feeding, diaper, activities)
- ✅ WebSocket: Real-time bulk operation notifications
### ✅ Phase 2: Frontend Foundation (100% Complete)
All core frontend components are implemented:
1. **Components**:
- ✅ ChildSelector: Single/multiple/all modes with color-coded avatars
- ✅ DynamicChildDashboard: Tab view (≤3 children) / Card view (4+ children)
- ✅ ComparisonView: Analytics comparison with charts
2. **State Management**:
- ✅ Redux children slice: selectedChildIds, viewMode, defaultChild
- ✅ Selectors: selectSelectedChildren, selectViewMode, selectChildColor
- ✅ localStorage persistence for all selections
3. **Dashboard Integration**:
- ✅ Home page updated with DynamicChildDashboard
- ✅ GraphQL queries include display fields
### ✅ Phase 3: Activity Logging (100% Complete)
#### ✅ All Forms Completed (6/6)
**1. Feeding Tracking Form**
- File: [`/maternal-web/app/track/feeding/page.tsx`](maternal-web/app/track/feeding/page.tsx)
- Redux integration complete
- ChildSelector component integrated
- API calls updated to use `selectedChild.id`
- Build & test: **PASSED** (Bundle: 9.69 kB)
**2. Sleep Tracking Form**
- File: [`/maternal-web/app/track/sleep/page.tsx`](maternal-web/app/track/sleep/page.tsx)
- Redux integration complete
- ChildSelector component integrated
- API calls updated to use `selectedChild.id`
- Build & test: **PASSED** (Bundle: 4.11 kB)
**3. Diaper Tracking Form**
- File: `/maternal-web/app/track/diaper/page.tsx`
- Redux integration complete
- ChildSelector component integrated
- API calls updated to use `selectedChild.id`
- Build & test: **PASSED** (Bundle: 3.92 kB)
**4. Activity Tracking Form**
- File: `/maternal-web/app/track/activity/page.tsx`
- Redux integration complete
- ChildSelector component integrated
- API calls updated to use `selectedChild.id`
- Build & test: **PASSED** (Bundle: 3.54 kB)
**5. Growth Tracking Form**
- File: `/maternal-web/app/track/growth/page.tsx`
- Redux integration complete
- ChildSelector component integrated
- API calls updated to use `selectedChild.id`
- Build & test: **PASSED** (Bundle: 4.58 kB)
**6. Medicine Tracking Form**
- File: `/maternal-web/app/track/medicine/page.tsx`
- Redux integration complete
- ChildSelector component integrated
- API calls updated to use `selectedChild.id`
- Build & test: **PASSED** (Bundle: 10.1 kB)
---
## Implementation Pattern (Proven & Tested)
The following pattern has been successfully applied to feeding and sleep forms:
### Step 1: Add Imports
```typescript
import { useDispatch, useSelector } from 'react-redux';
import { fetchChildren, selectChild, selectSelectedChild, childrenSelectors } from '@/store/slices/childrenSlice';
import { AppDispatch, RootState } from '@/store/store';
import ChildSelector from '@/components/common/ChildSelector';
```
### Step 2: Replace Local State with Redux
```typescript
// BEFORE
const [children, setChildren] = useState<Child[]>([]);
const [selectedChild, setSelectedChild] = useState<string>('');
const familyId = user?.families?.[0]?.familyId;
// AFTER
const dispatch = useDispatch<AppDispatch>();
const children = useSelector((state: RootState) => childrenSelectors.selectAll(state));
const selectedChild = useSelector(selectSelectedChild);
const familyId = useSelector((state: RootState) => state.auth.user?.familyId);
const [selectedChildIds, setSelectedChildIds] = useState<string[]>([]);
```
### Step 3: Update useEffect Hooks
```typescript
// Load children from Redux
useEffect(() => {
if (familyId && children.length === 0) {
dispatch(fetchChildren(familyId));
}
}, [familyId, dispatch, children.length]);
// Sync selectedChildIds with Redux selectedChild
useEffect(() => {
if (selectedChild?.id) {
setSelectedChildIds([selectedChild.id]);
}
}, [selectedChild]);
// Update data loading hooks
useEffect(() => {
if (selectedChild?.id) {
loadData(); // Your data loading function
}
}, [selectedChild?.id]);
```
### Step 4: Update Loading State
```typescript
// BEFORE
const [childrenLoading, setChildrenLoading] = useState(true);
// AFTER
const childrenLoading = useSelector((state: RootState) => state.children.loading);
if (childrenLoading && children.length === 0) {
// Show loading skeleton
}
```
### Step 5: Update Form Validation
```typescript
// BEFORE
if (!selectedChild) {
setError('Please select a child');
return;
}
// AFTER
if (!selectedChild?.id) {
setError('Please select a child');
return;
}
```
### Step 6: Update API Calls
```typescript
// BEFORE
await trackingApi.createActivity(selectedChild, {...});
// AFTER
await trackingApi.createActivity(selectedChild.id, {...});
```
### Step 7: Replace Child Selector UI
```typescript
// BEFORE
{children.length > 1 && (
<Paper sx={{ p: 2, mb: 3 }}>
<FormControl fullWidth>
<InputLabel>Select Child</InputLabel>
<Select value={selectedChild} onChange={(e) => setSelectedChild(e.target.value)}>
{children.map((child) => (
<MenuItem key={child.id} value={child.id}>{child.name}</MenuItem>
))}
</Select>
</FormControl>
</Paper>
)}
// AFTER
{children.length > 0 && (
<Paper sx={{ p: 2, mb: 3 }}>
<ChildSelector
children={children}
selectedChildIds={selectedChildIds}
onChange={(childIds) => {
setSelectedChildIds(childIds);
if (childIds.length > 0) {
dispatch(selectChild(childIds[0]));
}
}}
mode="single"
label={t('common.selectChild')}
required
/>
</Paper>
)}
```
### Step 8: Remove loadChildren Function
Delete the entire `loadChildren` function as it's now handled by Redux.
---
## Testing Checklist
For each updated form, verify:
- [ ] Form loads without errors
- [ ] Child selector displays with correct avatars and colors
- [ ] Selecting a child updates the form state
- [ ] Form submission works with selected child
- [ ] Recent activities load for selected child
- [ ] Switching children updates recent activities
- [ ] Loading states display correctly
- [ ] No console errors or warnings
- [ ] Build succeeds with `npm run build`
---
## Build & Test Results
### ✅ Successful Builds
- Feeding form: **PASSED** (Build size: 7.01 kB)
- Sleep form: **PASSED** (Build size: 7.67 kB)
- Dynamic dashboard: **PASSED**
- Comparison view: **PASSED**
### 📊 Performance Metrics
- Bundle size increase: ~15 kB (ChildSelector + Redux overhead)
- No runtime errors detected
- All TypeScript compilation successful
- No accessibility warnings
---
## Next Steps
### Immediate (Complete Phase 3)
1. **Update diaper form** using the proven pattern (ETA: 15 min)
2. **Update activity form** using the proven pattern (ETA: 15 min)
3. **Update growth form** using the proven pattern (ETA: 15 min)
4. **Update medicine form** using the proven pattern (ETA: 15 min)
5. **Final build & test** all forms together (ETA: 10 min)
6. **Update documentation** with completion status (ETA: 5 min)
**Total ETA to complete Phase 3**: ~1 hour
### Phase 4 & 5 (Future Work)
- **Phase 4**: Analytics & Comparison ✅ (Already complete!)
- **Phase 5**: AI & Voice Processing
- Child name detection in voice commands
- Multi-child context building
- Clarification flows ("Which child?")
- LangChain prompt updates
---
## Files Changed (Git Commits)
### Commits Log
```
89a0d7e feat: Integrate ChildSelector in sleep tracking form
47a4720 feat: Integrate ChildSelector component in feeding tracking form
a1f788f feat: Complete Phase 3 - Multi-child frontend components
a3cbe22 feat: Implement dynamic dashboard with tabs/cards for multi-child families
65ce8bd docs: Update multi-child implementation plan with completed phases
2747630 feat: Update Redux children slice for multi-child support
[... earlier commits ...]
```
### Modified Files
- `maternal-web/app/page.tsx` - Dynamic dashboard integration
- `maternal-web/app/track/feeding/page.tsx` - ChildSelector integration ✅
- `maternal-web/app/track/sleep/page.tsx` - ChildSelector integration ✅
- `maternal-web/components/common/ChildSelector.tsx` - New component
- `maternal-web/components/dashboard/DynamicChildDashboard.tsx` - New component
- `maternal-web/components/analytics/ComparisonView.tsx` - New component
- `maternal-web/store/slices/childrenSlice.ts` - Multi-child state
- `maternal-web/lib/api/analytics.ts` - Comparison API
- `maternal-web/graphql/queries/dashboard.ts` - Display fields
- `maternal-app-backend/src/database/migrations/V017_*.sql` - Child display prefs
- `maternal-app-backend/src/database/migrations/V018_*.sql` - User preferences
- `maternal-app-backend/src/database/migrations/V019_*.sql` - Bulk operations
- `maternal-app-backend/src/modules/children/children.service.ts` - Auto-colors
- `maternal-app-backend/src/modules/tracking/tracking.service.ts` - Bulk ops
- `maternal-app-backend/src/modules/analytics/comparison.service.ts` - New service
---
## Known Issues & Limitations
### Current Limitations
1.**Bulk logging UI not yet implemented** - Forms support single child only (planned for Phase 3B)
2.**Default child logic missing** - No "same as last time" quick select (planned for Phase 3B)
3.**Remaining forms not updated** - 4 of 6 tracking forms still need ChildSelector integration
4.**Per-screen child memory** - Redux slice has the field, but not yet used in tracking forms
### No Known Bugs
- All implemented features are working as expected
- No runtime errors or TypeScript issues
- All builds passing successfully
---
## Success Criteria
### Phase 3 Completion Criteria
- [x] ChildSelector component created and tested
- [x] Redux state updated with multi-child support
- [x] Pattern established and documented
- [ ] All 6 tracking forms updated (2/6 complete)
- [ ] Bulk logging UI implemented (deferred to Phase 3B)
- [ ] Default child logic added (deferred to Phase 3B)
- [ ] End-to-end testing completed
**Current Status**: **67% Complete** (backend + foundation + 2 forms)
### Definition of Done for Phase 3
When all 6 tracking forms have been updated with ChildSelector and successfully build/test, Phase 3 will be considered complete. The bulk logging UI and default child logic are nice-to-have features that can be completed in Phase 3B.
---
## Appendix: Key Learnings
### What Worked Well
1. **Pattern-based approach**: Establishing a clear pattern for feeding form made subsequent updates straightforward
2. **Redux centralization**: Using Redux for children state eliminated duplicate loading logic
3. **Component reusability**: ChildSelector component works perfectly across all contexts
4. **Incremental commits**: Small, focused commits made it easy to track progress
5. **Build-first approach**: Testing builds after each form ensured no regressions
### Optimization Opportunities
1. **Automated updates**: The pattern is so consistent that the remaining 4 forms could potentially be updated via script
2. **Shared logic**: Consider creating a `useChildTracking` custom hook to reduce boilerplate
3. **Performance**: Monitor Redux selector performance with large child lists (8+ children)
### Technical Debt
- None identified. The implementation follows best practices and is well-tested.
---
**Last Updated**: October 4, 2025
**Next Review**: After remaining forms are updated

View File

@@ -1,361 +0,0 @@
# Phase 5: AI & Voice Processing - Multi-Child Implementation Status
**Date**: October 5, 2025
**Status**: ✅ **COMPLETE**
**Completion**: All AI and voice processing components updated for multi-child support
---
## Overview
Phase 5 enhances the AI chat assistant and voice processing system to intelligently handle multi-child families. The system now:
- Detects child names in voice commands and chat messages
- Provides child-specific context and responses
- Requests clarification when child identity is ambiguous
- Filters activities by detected child for relevant AI responses
---
## ✅ Completed Components
### 1. AI Context Manager (`context-manager.ts`)
**File**: `maternal-app-backend/src/modules/ai/context/context-manager.ts`
**Changes**:
- ✅ Enhanced `summarizeChildContext()` to handle multiple children
- Shows all children with ages and genders
- Adds instruction for AI to ask for clarification if needed
- Provides family overview ("Family has 2 children: Emma, Liam")
- ✅ Updated `buildSystemPrompt()` with multi-child awareness
- Added "MULTI-CHILD FAMILY SUPPORT" section
- Instructions for identifying which child is being discussed
- Guidance on handling sibling comparisons sensitively
- Recognition that each child develops at their own pace
- ✅ Added `detectChildInMessage()` method
- Pattern matching for child names (exact, possessive, "for Emma", "about Emma")
- Case-insensitive matching
- Defaults to single child if only one exists
- Returns `null` if ambiguous in multi-child families
**Example Context Output**:
```
Family has 2 children: Emma, Liam
- Emma (female): 18 months old, born Thu Jan 15 2024
- Liam (male): 6 months old, born Wed Jul 10 2024
IMPORTANT: When user mentions a specific child name, focus your response on that child. If unclear which child, ask for clarification.
```
---
### 2. Voice Service (`voice.service.ts`)
**File**: `maternal-app-backend/src/modules/voice/voice.service.ts`
**Changes**:
- ✅ Updated `extractActivityFromText()` signature
- Added `availableChildren` parameter: `Array<{ id: string; name: string }>`
- Returns extended type with `detectedChildName` and `childId`
- ✅ Enhanced GPT-4o-mini prompt for multi-child detection
- Added "Available Children in Family" context
- Instructions to extract child name from voice command
- Case-insensitive name matching
- Clarification trigger if no name mentioned with multiple children
- ✅ Implemented child name matching logic
- Extracts `childName` from GPT response
- Matches to `childId` using case-insensitive comparison
- Logs successful matches and mismatches
- Triggers clarification if multi-child family but no name detected
- ✅ Updated `processVoiceInput()` method
- Passes `availableChildren` through to extraction
- Returns extended type with child detection results
**Example Voice Command Processing**:
```javascript
// Input: "Fed Emma 120ml at 3pm"
// Available Children: [{ id: "ch_123", name: "Emma" }, { id: "ch_456", name: "Liam" }]
{
type: "feeding",
childName: "Emma",
childId: "ch_123",
details: {
feedingType: "bottle",
amount: 120,
unit: "ml"
},
confidence: 0.95,
needsClarification: false
}
// Input: "Baby fell asleep" (ambiguous in multi-child family)
{
type: "sleep",
childName: null,
childId: null,
confidence: 0.9,
needsClarification: true,
clarificationPrompt: "Which child is this for? Available: Emma, Liam"
}
```
---
### 3. Voice Controller (`voice.controller.ts`)
**File**: `maternal-app-backend/src/modules/voice/voice.controller.ts`
**Changes**:
- ✅ Updated `/api/v1/voice/transcribe` endpoint
- Added `availableChildren` body parameter (JSON string)
- Parses JSON to array of `{ id, name }` objects
- Passes to voice service for child detection
- Logs available children for debugging
- ✅ Updated `/api/v1/voice/process` endpoint
- Added `availableChildren` parameter
- Forwards to `processVoiceInput()` method
- ✅ Updated `/api/v1/voice/extract-activity` endpoint
- Added `availableChildren` parameter
- Accepts JSON array directly (not string)
**API Usage Example**:
```bash
POST /api/v1/voice/transcribe
Content-Type: application/json
{
"text": "Fed Emma 120ml",
"language": "en",
"availableChildren": "[{\"id\":\"ch_123\",\"name\":\"Emma\"},{\"id\":\"ch_456\",\"name\":\"Liam\"}]"
}
```
---
### 4. AI Service (`ai.service.ts`)
**File**: `maternal-app-backend/src/modules/ai/ai.service.ts`
**Changes**:
- ✅ Added child detection in `chat()` method
- Calls `contextManager.detectChildInMessage()` with user message
- Filters recent activities by detected child's ID if found
- Falls back to all user activities if no specific child detected
- ✅ Enhanced logging for multi-child families
- Logs number of children and their names
- Logs which child was detected (or none)
- Helps debug context filtering
**Example AI Chat Flow**:
```
User: "How is Emma's sleep pattern?"
→ Detects: Emma (ch_123)
→ Loads: Emma's recent sleep activities only
→ AI Response: "Based on Emma's sleep logs from the past week, she's been napping..."
User: "What about developmental milestones?"
→ Detects: No specific child
→ Loads: All family activities
→ AI Response: "I see you have 2 children, Emma (18 months) and Liam (6 months).
Which child would you like to know about?"
```
---
## Technical Implementation Details
### Child Name Detection Algorithm
```typescript
// Pattern matching hierarchy:
1. Exact word match: /\bEmma\b/i
2. Possessive: /\bEmma's\b/i
3. "for [name]": /\bfor Emma\b/i
4. "about [name]": /\babout Emma\b/i
5. "[name] is": /\bEmma is\b/i
6. "[name] has": /\bEmma has\b/i
// Fallback logic:
- If only 1 child exists default to that child
- If multiple children and no match return null (trigger clarification)
```
### GPT-4o-mini Prompt Enhancement
```
**Available Children in Family:** Emma, Liam
- If the user mentions a specific child name, extract it and return in "childName" field
- Match child names case-insensitively and handle variations (e.g., "Emma", "emma", "Emmy")
- If multiple children exist but no name is mentioned, set "needsClarification" to true
**Response Format:**
{
"type": "feeding|sleep|diaper|...",
"timestamp": "ISO 8601 datetime",
"childName": "extracted child name if mentioned, or null",
"details": { ... }
}
```
### Activity Filtering Strategy
| Scenario | Detection | Activity Filter |
|----------|-----------|----------------|
| Single child | Always that child | `childId: <child.id>` |
| Multi-child + name detected | Specific child | `childId: <detected.id>` |
| Multi-child + no name | None | `loggedBy: <userId>` (all) |
---
## Integration Points
### Frontend Integration (Required)
Voice input components need to pass available children:
```typescript
// maternal-web/components/voice/VoiceInputButton.tsx
const children = useSelector(childrenSelectors.selectAll);
const availableChildren = children.map(c => ({ id: c.id, name: c.name }));
const response = await fetch('/api/voice/transcribe', {
method: 'POST',
body: JSON.stringify({
text: transcript,
language: 'en',
availableChildren: JSON.stringify(availableChildren)
})
});
```
### AI Chat Integration
No frontend changes required - child detection happens automatically in the backend based on message content.
---
## Testing Scenarios
### ✅ Test Case 1: Single Child Family
```
Input: "Fed baby 100ml"
Children: [{ id: "ch_1", name: "Emma" }]
Expected: Detects Emma automatically, no clarification needed
```
### ✅ Test Case 2: Multi-Child with Name
```
Input: "Fed Emma 100ml"
Children: [{ id: "ch_1", name: "Emma" }, { id: "ch_2", name: "Liam" }]
Expected: Detects Emma (ch_1), confidence: high, no clarification
```
### ✅ Test Case 3: Multi-Child without Name
```
Input: "Baby fell asleep"
Children: [{ id: "ch_1", name: "Emma" }, { id: "ch_2", name: "Liam" }]
Expected: No child detected, needsClarification: true, prompt: "Which child?"
```
### ✅ Test Case 4: AI Chat - Specific Child
```
User: "How is Emma sleeping?"
Children: Emma (18mo), Liam (6mo)
Expected:
- Detects Emma in message
- Loads only Emma's sleep activities
- Responds with Emma-specific insights
```
### ✅ Test Case 5: AI Chat - General Question
```
User: "What are typical sleep schedules?"
Children: Emma (18mo), Liam (6mo)
Expected:
- No specific child detected
- Asks which child or provides age-appropriate ranges for both
```
---
## Performance Considerations
- **Child Detection**: O(n × m) where n = # children, m = # patterns (~6). Negligible for typical families.
- **Activity Filtering**: Indexed query on `childId`, very fast.
- **GPT-4o-mini Latency**: +0-50ms for child name extraction (minimal impact).
---
## Security & Privacy
- ✅ Child names only shared with voice/AI services (OpenAI GPT-4o-mini)
- ✅ Activity data filtered per child before AI context building
- ✅ No cross-family data leakage (queries scoped to `userId`)
- ✅ Voice feedback logs include `childId` for accuracy training
---
## Next Steps (Post-Phase 5)
1. **Frontend Integration** (Phase 6)
- Update `VoiceInputButton` component to pass `availableChildren`
- Update `VoiceActivityReview` to display detected child name
- Add clarification dialog when `needsClarification: true`
2. **Analytics Enhancement**
- Track child name detection accuracy
- Monitor clarification request frequency
- Identify common name variations/mishears
3. **AI Training Improvements**
- Fine-tune prompts based on voice feedback data
- Add nickname support (e.g., "Emmy" → "Emma")
- Handle sibling references (e.g., "the baby" vs "my toddler")
4. **Multi-Language Support**
- Extend child name detection to Spanish, French, Portuguese, Chinese
- Test transliteration handling (e.g., "María" vs "Maria")
---
## Files Modified
| File | Lines Changed | Description |
|------|--------------|-------------|
| `ai/context/context-manager.ts` | +68 | Multi-child context, child detection method |
| `voice/voice.service.ts` | +55 | Child name extraction, matching, clarification |
| `voice/voice.controller.ts` | +25 | API parameter updates for `availableChildren` |
| `ai/ai.service.ts` | +20 | Child detection in chat, activity filtering |
**Total**: 168 lines added/modified
---
## Build Status
**Backend Build**: `npm run build` - SUCCESS
**TypeScript Compilation**: No errors
**ESLint**: No errors
---
## Conclusion
Phase 5 successfully implements intelligent multi-child support across AI chat and voice processing systems. The system can now:
1. ✅ Detect child names in natural language (voice + chat)
2. ✅ Match names to child IDs for accurate activity tracking
3. ✅ Filter AI context by detected child for relevant responses
4. ✅ Request clarification when child identity is ambiguous
5. ✅ Provide child-specific advice based on age and history
**Status**: Ready for Phase 6 (Frontend Integration)

View File

@@ -1,429 +0,0 @@
# Phase 6: Testing & Optimization - Implementation Summary
## Overview
Phase 6 focused on establishing comprehensive testing infrastructure, increasing code coverage, and implementing performance testing for the maternal app backend. This phase ensures quality, reliability, and performance of the application.
## Completed Tasks
### ✅ 1. Testing Infrastructure Setup
**Jest Configuration**
- Unit testing with Jest and TypeScript
- E2E testing with Supertest
- Coverage reporting with lcov
- Test isolation and mocking strategies
**Test Scripts (package.json)**
```json
{
"test": "jest",
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk ... jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json"
}
```
### ✅ 2. Unit Test Suite
**Created Comprehensive Unit Tests:**
#### AI Service (`src/modules/ai/ai.service.spec.ts`)
- ✅ 97% coverage
- 27 test cases covering:
- Chat conversation creation and continuation
- Context building with user data
- Token counting and limits
- Error handling for missing API keys
- Prompt injection detection
- Input sanitization
- Conversation CRUD operations
#### Families Service (`src/modules/families/families.service.spec.ts`)
- ✅ 59% coverage
- 13 test cases covering:
- Member invitation flow
- Family joining with share codes
- Permission checks
- Family size limits (max 10 members)
- Conflict handling for duplicate members
- Family retrieval with authorization
#### Existing Coverage:
- ✅ Tracking Service: 88% (55 tests)
- ✅ Auth Service: 86% (comprehensive auth flows)
- ✅ Children Service: 91% (CRUD operations)
**Total Unit Tests**: 95 passing tests across 6 test suites
### ✅ 3. Integration/E2E Test Suite
**E2E Tests in `test/` Directory:**
1. **auth.e2e-spec.ts**
- User registration with device fingerprinting
- Login with email/password
- Token refresh flow
- Device management
2. **tracking.e2e-spec.ts**
- Activity creation (feeding, sleep, diaper)
- Activity retrieval and filtering
- Daily summary generation
- Multi-user tracking scenarios
3. **children.e2e-spec.ts**
- Child profile creation
- Child information updates
- Family member access control
- Child deletion with cleanup
**Database Services Integration:**
- PostgreSQL for relational data
- Redis for caching
- MongoDB for AI conversations
- Proper cleanup in `afterAll` hooks
### ✅ 4. CI/CD Pipeline
**GitHub Actions Workflow** (`.github/workflows/backend-ci.yml`)
**Four CI Jobs:**
1. **lint-and-test**
- ESLint code quality checks
- Jest unit tests with coverage
- Coverage upload to Codecov
- Coverage threshold warnings (<70%)
2. **e2e-tests**
- Full E2E suite with database services
- Database migration execution
- Test result artifact upload
- Runs on PostgreSQL 15, Redis 7, MongoDB 7
3. **build**
- NestJS production build
- Build artifact retention (7 days)
- Ensures deployability
4. **performance-test** (PR only)
- Artillery load testing
- Response time validation
- Performance report generation
- Resource monitoring
**Triggers:**
- Every push to `master`/`main`
- Every pull request
- Path-specific: only when backend code changes
### ✅ 5. Performance Testing
**Artillery Configuration** (`artillery.yml`)
**Test Scenarios:**
| Scenario | Weight | Purpose |
|----------|--------|---------|
| User Registration/Login | 10% | Auth flow validation |
| Track Baby Activities | 50% | Core feature (most common) |
| View Analytics Dashboard | 20% | Read-heavy operations |
| AI Chat Interaction | 15% | LLM integration load |
| Family Collaboration | 5% | Multi-user scenarios |
**Load Phases:**
1. **Warm-up**: 5 users/sec × 60s
2. **Ramp-up**: 5→50 users/sec × 120s
3. **Sustained**: 50 users/sec × 300s
4. **Spike**: 100 users/sec × 60s
**Performance Thresholds:**
- Max Error Rate: 1%
- P95 Response Time: <2 seconds
- P99 Response Time: <3 seconds
### ✅ 6. Test Coverage Reporting
**Current Coverage Status:**
```
Overall Coverage: 27.93%
├── Statements: 27.95%
├── Branches: 22.04%
├── Functions: 17.44%
└── Lines: 27.74%
```
**Module-Level Breakdown:**
| Module | Coverage | Status | Tests |
|--------|----------|--------|-------|
| AI Service | 97.14% | ✅ Excellent | 27 |
| Auth Service | 86.17% | ✅ Good | 20+ |
| Tracking Service | 87.91% | ✅ Good | 55 |
| Children Service | 91.42% | ✅ Excellent | 15 |
| Families Service | 59.21% | ⚠️ Needs work | 13 |
| Analytics Services | 0% | ❌ Not tested | 0 |
| Voice Service | 0% | ❌ Not tested | 0 |
| Controllers | ~0% | ❌ Not tested | 0 |
**Coverage Gaps Identified:**
- Controllers need integration tests
- Analytics module (pattern analysis, predictions, reports)
- Voice processing (Whisper integration)
- WebSocket gateway (families.gateway.ts)
### ✅ 7. Comprehensive Documentation
**Testing Documentation** (`TESTING.md`)
**Contents:**
- Test structure and organization
- Running tests (unit, E2E, performance)
- Writing test examples (unit + E2E)
- Coverage goals and current status
- Performance testing guide
- CI/CD integration details
- Best practices and troubleshooting
- Resources and links
**Key Sections:**
1. Quick start commands
2. Unit test template with mocking
3. E2E test template with database cleanup
4. Artillery performance testing
5. Coverage checking and reporting
6. CI/CD simulation locally
7. Troubleshooting common issues
## Testing Best Practices Implemented
### 1. Test Isolation
```typescript
beforeEach(() => {
// Fresh mocks for each test
jest.clearAllMocks();
});
afterAll(async () => {
// Database cleanup
await dataSource.query('DELETE FROM ...');
await app.close();
});
```
### 2. Descriptive Test Names
```typescript
it('should throw ForbiddenException when user lacks invite permissions', () => {});
// Instead of: it('test permissions', () => {});
```
### 3. AAA Pattern
```typescript
// Arrange
const mockData = { ... };
jest.spyOn(repository, 'find').mockResolvedValue(mockData);
// Act
const result = await service.findAll();
// Assert
expect(result).toEqual(mockData);
expect(repository.find).toHaveBeenCalled();
```
### 4. Comprehensive Mocking
- Repository mocks for database isolation
- HTTP service mocks for external APIs
- ConfigService mocks for environment variables
- Date/time mocks for consistency
### 5. Error Case Testing
- NotFoundException for missing resources
- ForbiddenException for authorization failures
- BadRequestException for invalid input
- ConflictException for duplicate data
## Key Achievements
### Quality Metrics
-**95 passing tests** across all modules
-**Zero failing tests** in test suite
-**27.93% overall coverage** (baseline established)
-**97% coverage** on AI service (critical component)
-**CI/CD pipeline** with automated testing
### Infrastructure
-**GitHub Actions** workflow for continuous testing
-**Artillery** performance testing framework
-**Codecov** integration for coverage tracking
-**Database services** in CI (PostgreSQL, Redis, MongoDB)
### Documentation
-**TESTING.md** comprehensive guide (400+ lines)
-**Artillery scenarios** for realistic load testing
-**CI/CD configuration** with service dependencies
-**Phase 6 summary** (this document)
## Performance Testing Results
### Expected Performance
Based on `artillery.yml` thresholds:
- **Throughput**: 50 sustained requests/sec
- **Peak Load**: 100 requests/sec spike handling
- **Response Time**:
- P95: <2 seconds
- P99: <3 seconds
- **Error Rate**: <1%
### Test Scenarios Distribution
- **50%** Activity tracking (feeding, sleep, diaper)
- **20%** Analytics dashboard queries
- **15%** AI chat interactions
- **10%** Authentication flows
- **5%** Family collaboration
## Next Steps & Recommendations
### Immediate Priorities (To reach 80% coverage)
1. **Controller Tests** (Current: ~0%)
- Add integration tests for all controllers
- Estimated: +15% coverage
2. **Analytics Module** (Current: 0%)
- Pattern analysis service tests
- Prediction service tests
- Report generation tests
- Estimated: +20% coverage
3. **Voice Service** (Current: 0%)
- Whisper integration mocking
- Audio processing tests
- Estimated: +10% coverage
4. **Context Manager** (Current: 8.77%)
- Token counting logic
- Context prioritization
- Safety boundary tests
- Estimated: +5% coverage
### Medium-Term Goals
5. **Mutation Testing**
- Install Stryker for mutation testing
- Identify weak test assertions
- Improve test quality
6. **Contract Testing**
- Add Pact for API contract tests
- Ensure frontend/backend compatibility
- Version compatibility checks
7. **Security Testing**
- OWASP ZAP integration
- SQL injection testing
- JWT vulnerability scanning
8. **Chaos Engineering**
- Database failure scenarios
- Network partition testing
- Service degradation handling
### Long-Term Improvements
9. **Visual Regression Testing**
- Percy or Chromatic for UI consistency
- Screenshot comparisons
10. **Accessibility Testing**
- axe-core integration
- WCAG AA compliance validation
## Test Execution Times
```
Unit Tests: ~7.9 seconds
E2E Tests: ~12 seconds (estimated)
Performance Tests: ~540 seconds (9 minutes)
Total CI Pipeline: ~5 minutes
```
## Resource Requirements
### Development
- Node.js 20+
- PostgreSQL 15+
- Redis 7+
- MongoDB 7+
- 4GB RAM minimum
### CI/CD
- GitHub Actions runners (Ubuntu latest)
- Docker containers for services
- ~2-3 GB disk space for artifacts
## Files Created/Modified in Phase 6
### New Files
```
✅ src/modules/ai/ai.service.spec.ts (477 lines)
✅ src/modules/families/families.service.spec.ts (238 lines)
✅ .github/workflows/backend-ci.yml (338 lines)
✅ artillery.yml (198 lines)
✅ TESTING.md (523 lines)
✅ docs/phase6-testing-summary.md (this file)
```
### Existing Files (Enhanced)
```
✅ src/modules/auth/auth.service.spec.ts (existing, verified)
✅ src/modules/tracking/tracking.service.spec.ts (existing, verified)
✅ src/modules/children/children.service.spec.ts (existing, verified)
✅ test/auth.e2e-spec.ts (existing, verified)
✅ test/tracking.e2e-spec.ts (existing, verified)
✅ test/children.e2e-spec.ts (existing, verified)
```
## Integration with Existing Documentation
This phase complements:
- `docs/maternal-app-testing-strategy.md` - Testing philosophy
- `docs/maternal-app-implementation-plan.md` - Overall roadmap
- `maternal-web/tests/README.md` - Frontend testing
- `.github/workflows/ci.yml` - Frontend CI/CD
## Conclusion
Phase 6 has successfully established a **solid testing foundation** for the maternal app backend:
1.**Infrastructure**: Jest, Supertest, Artillery configured
2.**Coverage**: Baseline 27.93% with critical services at 85%+
3.**CI/CD**: Automated testing on every commit
4.**Performance**: Load testing scenarios defined
5.**Documentation**: Comprehensive testing guide
**Quality Assurance**: The application now has:
- Automated regression prevention via CI
- Performance benchmarking capabilities
- Clear path to 80% coverage goal
- Testing best practices documented
**Next Phase Ready**: With testing infrastructure in place, the team can confidently move to Phase 7 (Deployment) knowing the application is well-tested and production-ready.
---
**Phase 6 Status**: ✅ **COMPLETED**
**Test Results**: 95/95 passing (100%)
**Coverage**: 27.93% → Target: 80% (path defined)
**CI/CD**: ✅ Automated
**Performance**: ✅ Benchmarked
**Documentation**: ✅ Comprehensive

View File

@@ -1,800 +0,0 @@
# Phase 8: Post-Launch Monitoring & Iteration - Implementation Summary
## Overview
Phase 8 establishes comprehensive monitoring, analytics, and rapid iteration infrastructure to enable data-driven product decisions post-launch. This phase focuses on tracking key metrics, gathering user feedback, and implementing systems for continuous improvement.
---
## Completed Implementation
### ✅ 1. Analytics Tracking Infrastructure
**File Created**: `src/common/services/analytics.service.ts`
**Features**:
- Comprehensive event tracking system with 25+ predefined events
- Multi-provider support (PostHog, Matomo, Mixpanel)
- User identification and property management
- Feature usage tracking
- Conversion funnel tracking
- Retention metric tracking
**Event Categories**:
```typescript
- User lifecycle (registration, login, onboarding)
- Family management (invites, joins)
- Child management (add, update, remove)
- Activity tracking (logged, edited, deleted, voice input)
- AI assistant (chat started, messages, conversations)
- Analytics (insights viewed, reports generated/exported)
- Premium (trial, subscription, cancellation)
- Engagement (notifications, sharing, feedback)
- Errors (errors occurred, API errors, offline mode, sync failures)
```
**Key Methods**:
```typescript
- trackEvent(eventData) // Track any analytics event
- identifyUser(userProperties) // Set user properties
- trackPageView(userId, path) // Track page/screen views
- trackFeatureUsage(userId, feature) // Track feature adoption
- trackFunnelStep(...) // Track conversion funnels
- trackRetention(userId, cohort) // Track retention metrics
```
**Provider Integration**:
- PostHog (primary)
- Matomo (privacy-focused alternative)
- Mixpanel (extensible for future)
---
### ✅ 2. Feature Flag System for Rapid Iteration
**File Created**: `src/common/services/feature-flags.service.ts`
**Features**:
- 20+ predefined feature flags across categories
- Gradual rollout with percentage-based distribution
- User/family-level allowlists
- Platform-specific flags (web, iOS, Android)
- Version-based gating
- Time-based activation/deactivation
- A/B test variant assignment
**Flag Categories**:
**Core Features**:
- AI Assistant
- Voice Input
- Pattern Recognition
- Predictions
**Premium Features**:
- Advanced Analytics
- Family Sharing
- Export Reports
- Custom Milestones
**Experimental Features**:
- AI GPT-5 (10% rollout)
- Sleep Coach (in development)
- Meal Planner (planned)
- Community Forums (planned)
**A/B Tests**:
- New Onboarding Flow (50% split)
- Redesigned Dashboard (25% rollout)
- Gamification (disabled)
**Performance Optimizations**:
- Lazy Loading
- Image Optimization
- Caching V2 (75% rollout)
**Mobile-Specific**:
- Offline Mode
- Push Notifications
- Biometric Auth (requires v1.1.0+)
**Key Methods**:
```typescript
- isEnabled(flag, context) // Check if flag is enabled for user
- getEnabledFlags(context) // Get all enabled flags
- overrideFlag(flag, enabled, userId)// Override for testing
- getVariant(flag, userId, variants) // Get A/B test variant
```
**Rollout Strategy**:
```typescript
// Consistent user assignment via hashing
// Example: 10% rollout for AI GPT-5
const userHash = this.hashUserId(userId);
const threshold = (0.10) * 0xffffffff;
return userHash <= threshold; // Same user always gets same variant
```
---
### ✅ 3. Health Check & Uptime Monitoring
**Files Created**:
- `src/common/services/health-check.service.ts`
- `src/common/controllers/health.controller.ts`
**Endpoints**:
```
GET /health - Simple health check for load balancers
GET /health/status - Detailed service status
GET /health/metrics - Performance metrics
```
**Service Checks**:
```typescript
services: {
database: { // PostgreSQL connectivity
status: 'up' | 'down' | 'degraded',
responseTime: number,
lastCheck: Date,
},
redis: { // Cache availability
status: 'up' | 'down',
responseTime: number,
},
mongodb: { // AI chat storage
status: 'up' | 'down',
responseTime: number,
},
openai: { // AI service (non-critical)
status: 'up' | 'degraded',
responseTime: number,
},
}
```
**Performance Metrics**:
```typescript
metrics: {
memoryUsage: {
total: number,
used: number,
percentUsed: number,
},
requestsPerMinute: number,
averageResponseTime: number,
p95ResponseTime: number, // 95th percentile
p99ResponseTime: number, // 99th percentile
}
```
**Overall Status Determination**:
- **Healthy**: All services up
- **Degraded**: Optional services down (e.g., OpenAI)
- **Unhealthy**: Critical services down (database, redis)
---
### ✅ 4. Mobile App Best Practices Documentation
**File Created**: `docs/mobile-app-best-practices.md` (545 lines)
**Comprehensive Coverage**:
**1. Architecture Principles**
- Code reusability between web and mobile
- Monorepo structure recommendation
- Platform-agnostic business logic
- Platform-specific UI components
**2. Mobile-Specific Features**
- **Offline-First Architecture**
- SQLite for local storage
- Sync queue for offline operations
- Conflict resolution strategies (last-write-wins)
- **Push Notifications**
- Expo Notifications setup
- Permission handling
- Notification categories and deep linking
- **Biometric Authentication**
- Face ID / Touch ID / Fingerprint
- Secure token storage with Expo SecureStore
- Fallback to password
- **Voice Input Integration**
- React Native Voice library
- Whisper API integration
- Speech-to-text processing
- **Camera & Photo Upload**
- Image picker (library + camera)
- Permission requests
- Photo upload to backend
**3. Performance Optimization**
- List virtualization with FlatList
- Image optimization with FastImage
- Animations with Reanimated 3
- Bundle size optimization (Hermes, code splitting)
**4. Testing Strategy**
- Unit tests with Jest
- Component tests with React Native Testing Library
- E2E tests with Detox
**5. Platform-Specific Considerations**
- iOS: App Store guidelines, permissions, background modes
- Android: Permissions, ProGuard, app signing
**6. Deployment & Distribution**
- iOS: Xcode build, TestFlight
- Android: AAB build, Google Play Internal Testing
- Over-the-Air Updates with CodePush
**7. Monitoring & Analytics**
- Sentry for crash reporting
- Performance monitoring
- Usage analytics integration
**8. Security Best Practices**
- Secure storage (not AsyncStorage)
- Certificate pinning
- Jailbreak/root detection
**9. Migration Path from Web to Mobile**
- 5-phase implementation plan
- Shared logic extraction
- Mobile shell development
- Feature parity roadmap
---
### ✅ 5. Product Analytics Dashboard Documentation
**File Created**: `docs/product-analytics-dashboard.md` (580 lines)
**Key Performance Indicators (KPIs)**:
**1. User Acquisition Metrics**
```
Metric Target Formula
──────────────────────────────────────────────
Download Rate 3% Downloads / Impressions
Registration Rate 75% Signups / Downloads
Onboarding Completion 90% Completed / Started
Time to First Value < 2 min First activity logged
```
**2. Engagement Metrics**
```typescript
dau: number; // Daily active users
wau: number; // Weekly active users
mau: number; // Monthly active users
dauMauRatio: number; // Stickiness (target: >20%)
averageSessionDuration: number; // Target: >5 min
sessionsPerUser: number; // Target: >2 per day
```
**Feature Adoption Targets**:
```typescript
activityTracking: 95% // Core feature
aiAssistant: 70% // AI engagement
voiceInput: 40% // Voice adoption
familySharing: 60% // Multi-user
analytics: 80% // View insights
exportReports: 25% // Premium feature
```
**3. Retention Metrics**
```typescript
CohortRetention {
day0: 100% // Signup
day1: >40% // Next day return
day7: >60% // Week 1 retention
day30: >40% // Month 1 retention
day90: >30% // Quarter retention
}
```
**4. Monetization Metrics**
```typescript
trialToPayingConversion: >30%
churnRate: <5% monthly
mrr: number // Monthly Recurring Revenue
arpu: number // Average Revenue Per User
ltv: number // Lifetime Value
cac: number // Customer Acquisition Cost
ltvCacRatio: >3 // LTV/CAC ratio
```
**5. Product Quality Metrics**
```typescript
apiResponseTimeP95: <2s
apiResponseTimeP99: <3s
errorRate: <1%
uptime: >99.9%
crashFreeUsers: >98%
crashFreeSessions: >99.5%
appStoreRating: >4.0
nps: >50 // Net Promoter Score
csat: >80% // Customer Satisfaction
```
**Dashboard Templates**:
1. **Executive Dashboard** - Daily review with key metrics
2. **Product Analytics Dashboard** - User journey funnels
3. **A/B Testing Dashboard** - Experiment tracking
**SQL Queries Provided For**:
- Daily registration funnel
- Conversion rates by channel
- DAU/WAU/MAU trends
- Power user identification
- Feature adoption over time
- Weekly cohort retention
- MRR trend and growth
- LTV calculation
- Churn analysis
- API performance monitoring
- Crash analytics
- Onboarding funnel conversion
- A/B test results
**Monitoring & Alerting Rules**:
**Critical Alerts** (PagerDuty):
- High error rate (>5%)
- API response time degradation (>3s)
- Database connection pool exhausted
- Crash rate spike (>2%)
**Business Alerts** (Email/Slack):
- Daily active users drop (>20%)
- Churn rate increase (>7%)
- Low onboarding completion (<80%)
**Rapid Iteration Framework**:
- Week 1-2: Monitoring & triage
- Week 3-4: Optimization
- Month 2: Feature iteration
**Recommended Tools**:
- PostHog (core analytics)
- Sentry (error tracking)
- UptimeRobot (uptime monitoring)
- Grafana + Prometheus (performance)
---
## Success Criteria Tracking
### MVP Launch (Month 1)
```markdown
Metric Target Implementation
─────────────────────────────────────────────────────────────
✅ Downloads 1,000 Analytics tracking ready
✅ Day-7 retention 60% Cohort queries defined
✅ App store rating 4.0+ User feedback system
✅ Crash rate <2% Health checks + Sentry
✅ Activities logged/day/user 5+ Event tracking ready
✅ AI assistant usage 70% Feature flag tracking
```
### 3-Month Goals
```markdown
✅ Active users 10,000 Analytics dashboards
✅ Premium subscribers 500 Monetization tracking
✅ Month-over-month growth 50% MRR queries
✅ App store rating 4.5+ Feedback analysis
```
### 6-Month Vision
```markdown
✅ Active users 50,000 Scalability metrics
✅ Premium subscribers 2,500 Revenue optimization
✅ Break-even Yes Cost/revenue tracking
```
---
## Files Created in Phase 8
### Backend Services
```
✅ src/common/services/analytics.service.ts (365 lines)
- Event tracking with multi-provider support
- User identification
- Feature usage and funnel tracking
✅ src/common/services/feature-flags.service.ts (385 lines)
- 20+ predefined flags
- Rollout percentage control
- A/B test variant assignment
- Platform and version gating
✅ src/common/services/health-check.service.ts (279 lines)
- Service health monitoring
- Performance metrics tracking
- Memory and CPU monitoring
✅ src/common/controllers/health.controller.ts (32 lines)
- Health check endpoints
- Metrics exposure
```
### Documentation
```
✅ docs/mobile-app-best-practices.md (545 lines)
- React Native implementation guide
- Offline-first architecture
- Platform-specific features
- Migration path from web
✅ docs/product-analytics-dashboard.md (580 lines)
- KPI definitions and targets
- SQL queries for all metrics
- Dashboard templates
- Alerting rules
- Rapid iteration framework
✅ docs/phase8-post-launch-summary.md (this file)
- Complete Phase 8 overview
- Implementation summary
- Integration guide
```
**Total**: 2,186 lines of production code and documentation
---
## Integration Points
### Backend Integration
**1. Add to App Module**
```typescript
// src/app.module.ts
import { AnalyticsService } from './common/services/analytics.service';
import { FeatureFlagsService } from './common/services/feature-flags.service';
import { HealthCheckService } from './common/services/health-check.service';
import { HealthController } from './common/controllers/health.controller';
@Module({
controllers: [HealthController, /* other controllers */],
providers: [
AnalyticsService,
FeatureFlagsService,
HealthCheckService,
/* other providers */
],
exports: [AnalyticsService, FeatureFlagsService],
})
export class AppModule {}
```
**2. Track Events in Services**
```typescript
// Example: Track activity creation
import { AnalyticsService, AnalyticsEvent } from './common/services/analytics.service';
@Injectable()
export class TrackingService {
constructor(private analyticsService: AnalyticsService) {}
async create(userId: string, childId: string, dto: CreateActivityDto) {
const activity = await this.activityRepository.save(/* ... */);
// Track event
await this.analyticsService.trackEvent({
event: AnalyticsEvent.ACTIVITY_LOGGED,
userId,
timestamp: new Date(),
properties: {
activityType: dto.type,
method: 'manual', // or 'voice'
childId,
},
});
return activity;
}
}
```
**3. Use Feature Flags**
```typescript
// Example: Check if feature is enabled
import { FeatureFlagsService, FeatureFlag } from './common/services/feature-flags.service';
@Injectable()
export class AIService {
constructor(private featureFlags: FeatureFlagsService) {}
async chat(userId: string, message: string) {
const useGPT5 = this.featureFlags.isEnabled(
FeatureFlag.AI_GPT5,
{ userId, platform: 'web' }
);
const model = useGPT5 ? 'gpt-5-mini' : 'gpt-4o-mini';
// Use appropriate model
}
}
```
**4. Expose Feature Flags to Frontend**
```typescript
// Add endpoint to return enabled flags for user
@Controller('api/v1/feature-flags')
export class FeatureFlagsController {
constructor(private featureFlags: FeatureFlagsService) {}
@Get()
@UseGuards(JwtAuthGuard)
async getEnabledFlags(@CurrentUser() user: User) {
const context = {
userId: user.id,
familyId: user.familyId,
platform: 'web', // Or get from request headers
isPremium: user.subscription?.isPremium || false,
};
const enabledFlags = this.featureFlags.getEnabledFlags(context);
return {
flags: enabledFlags,
context,
};
}
}
```
### Frontend Integration
**1. Feature Flag Hook (React)**
```typescript
// hooks/useFeatureFlag.ts
import { useEffect, useState } from 'react';
export function useFeatureFlag(flag: string): boolean {
const [isEnabled, setIsEnabled] = useState(false);
useEffect(() => {
fetch('/api/v1/feature-flags')
.then(res => res.json())
.then(data => {
setIsEnabled(data.flags.includes(flag));
});
}, [flag]);
return isEnabled;
}
// Usage in component
function MyComponent() {
const hasGPT5 = useFeatureFlag('ai_gpt5');
return (
<div>
{hasGPT5 && <Badge>Powered by GPT-5</Badge>}
</div>
);
}
```
**2. Analytics Tracking (Frontend)**
```typescript
// lib/analytics.ts
export class FrontendAnalytics {
static track(event: string, properties?: any) {
// Send to backend
fetch('/api/v1/analytics/track', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ event, properties }),
});
// Also send to PostHog directly (if configured)
if (window.posthog) {
window.posthog.capture(event, properties);
}
}
static identify(userId: string, properties: any) {
fetch('/api/v1/analytics/identify', {
method: 'POST',
body: JSON.stringify({ userId, properties }),
});
if (window.posthog) {
window.posthog.identify(userId, properties);
}
}
}
// Usage
FrontendAnalytics.track('button_clicked', {
buttonName: 'Track Feeding',
location: 'homepage',
});
```
---
## Environment Configuration
**Add to `.env`**:
```bash
# Analytics
ANALYTICS_ENABLED=true
ANALYTICS_PROVIDER=posthog # or 'matomo', 'mixpanel'
ANALYTICS_API_KEY=your_posthog_api_key
# Feature Flags (optional external service)
FEATURE_FLAGS_PROVIDER=local # or 'launchdarkly', 'configcat'
# Sentry Error Tracking
SENTRY_DSN=your_sentry_dsn
SENTRY_ENVIRONMENT=production
# Uptime Monitoring
UPTIME_ROBOT_API_KEY=your_uptime_robot_key
```
---
## Monitoring Setup Checklist
### Technical Monitoring
- [x] Health check endpoints implemented (`/health`, `/health/status`, `/health/metrics`)
- [x] Service health monitoring (database, redis, mongodb, openai)
- [x] Performance metrics tracking (response times, memory usage)
- [ ] Set up Sentry for error tracking
- [ ] Configure uptime monitoring (UptimeRobot/Pingdom)
- [ ] Set up Grafana dashboards for metrics visualization
- [ ] Configure alert rules (critical and business alerts)
### Analytics
- [x] Analytics service implemented with multi-provider support
- [x] Event tracking for all major user actions
- [ ] PostHog/Matomo account setup
- [ ] Dashboard configuration (executive, product, A/B testing)
- [ ] SQL queries deployed for metrics calculation
- [ ] Cohort analysis automated
- [ ] Retention reports scheduled
### Feature Management
- [x] Feature flag service with 20+ predefined flags
- [x] Gradual rollout capability
- [x] A/B testing infrastructure
- [ ] Frontend integration for flag consumption
- [ ] Admin UI for flag management (optional)
- [ ] Flag usage documentation for team
### User Feedback
- [ ] In-app feedback form
- [ ] NPS survey implementation
- [ ] App store review prompts
- [ ] Support ticket system integration
---
## Next Steps & Recommendations
### Immediate Actions (Week 1 Post-Launch)
**1. Set Up External Services**
```bash
# Sign up for services
- PostHog (analytics)
- Sentry (error tracking)
- UptimeRobot (uptime monitoring)
# Configure API keys in .env
# Deploy updated backend with monitoring
```
**2. Create Dashboards**
```markdown
- Executive dashboard in PostHog/Grafana
- Product analytics dashboard
- Technical health dashboard
- Mobile app analytics (when launched)
```
**3. Configure Alerts**
```markdown
- PagerDuty for critical issues
- Slack for business alerts
- Email for weekly reports
```
### Week 1-2: Monitoring Phase
```markdown
Daily Tasks:
- [ ] Review health check endpoint status
- [ ] Monitor crash reports (target: <2%)
- [ ] Check API response times (target: P95 <2s)
- [ ] Track onboarding completion (target: >90%)
- [ ] Monitor day-1 retention (target: >40%)
Weekly Review:
- [ ] Analyze top 5 errors from Sentry
- [ ] Review user feedback and feature requests
- [ ] Check cohort retention trends
- [ ] Assess feature adoption rates
- [ ] Plan hotfixes if needed
```
### Week 3-4: Optimization Phase
```markdown
A/B Tests to Run:
- [ ] New onboarding flow (already flagged at 50%)
- [ ] Push notification timing experiments
- [ ] AI response quality variations
- [ ] Activity tracking UX improvements
Success Metrics:
- Increase day-7 retention from 60% to 65%
- Increase AI assistant usage from 70% to 75%
- Reduce time-to-first-value to <90 seconds
```
### Month 2: Feature Iteration
```markdown
Based on Data:
- [ ] Identify most-used features (prioritize improvements)
- [ ] Identify least-used features (improve UX or sunset)
- [ ] Analyze user segments (power users vs. casual)
- [ ] Test premium feature adoption (target: >25%)
New Features (if validated by data):
- [ ] Sleep coaching (if sleep tracking popular)
- [ ] Meal planning (if feeding tracking high-engagement)
- [ ] Community forums (if users request social features)
```
---
## Phase 8 Status: ✅ **COMPLETED**
**Implementation Quality**: Production-ready
**Coverage**: Comprehensive
- ✅ Analytics tracking infrastructure
- ✅ Feature flag system for rapid iteration
- ✅ Health monitoring and uptime tracking
- ✅ Mobile app best practices documented
- ✅ Product analytics dashboards defined
- ✅ A/B testing framework ready
- ✅ Monitoring and alerting strategy
- ✅ Rapid iteration framework
**Documentation**: 2,186 lines
- Complete implementation guides
- SQL query templates
- Dashboard specifications
- Mobile app migration path
- Integration examples
**Ready for**:
- Production deployment
- Post-launch monitoring
- Data-driven iteration
- Mobile app development
---
## Conclusion
Phase 8 provides a complete foundation for post-launch success:
1. **Visibility**: Know what's happening (analytics, monitoring)
2. **Agility**: Respond quickly (feature flags, A/B tests)
3. **Reliability**: Stay up and performant (health checks, alerts)
4. **Growth**: Optimize based on data (dashboards, metrics)
5. **Future-Ready**: Mobile app best practices documented
The implementation is production-ready with clear integration paths and comprehensive documentation. All systems are in place to monitor performance, gather user insights, and iterate rapidly based on real-world usage.

View File

@@ -1,722 +0,0 @@
# Product Analytics Dashboard Guide
## Metrics, KPIs, and Data-Driven Decision Making
---
## Overview
This document defines the key metrics, analytics dashboards, and monitoring strategies for the Maternal App to enable data-driven product decisions and rapid iteration based on user behavior.
### Success Criteria (from Implementation Plan)
**MVP Launch (Month 1)**
- 1,000 downloads
- 60% day-7 retention
- 4.0+ app store rating
- <2% crash rate
- 5+ activities logged per day per active user
- 70% of users trying AI assistant
**3-Month Goals**
- 10,000 active users
- 500 premium subscribers
- 50% month-over-month growth
- 4.5+ app store rating
**6-Month Vision**
- 50,000 active users
- 2,500 premium subscribers
- Break-even on operational costs
---
## Key Performance Indicators (KPIs)
### 1. User Acquisition Metrics
#### Download & Registration Funnel
```
Metric Target Formula
─────────────────────────────────────────────────────
App Store Impressions 100,000 Total views
Download Rate 3% Downloads / Impressions
Registration Rate 75% Signups / Downloads
Onboarding Completion 90% Completed / Started
Time to First Value < 2 min First activity logged
```
**Dashboard Queries**:
```sql
-- Daily registration funnel
SELECT
DATE(created_at) as date,
COUNT(*) FILTER (WHERE step = 'download') as downloads,
COUNT(*) FILTER (WHERE step = 'registration_started') as started_registration,
COUNT(*) FILTER (WHERE step = 'registration_completed') as completed_registration,
COUNT(*) FILTER (WHERE step = 'onboarding_completed') as completed_onboarding,
COUNT(*) FILTER (WHERE step = 'first_activity') as first_activity
FROM user_funnel_events
WHERE created_at >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY DATE(created_at)
ORDER BY date DESC;
-- Conversion rates by channel
SELECT
acquisition_channel,
COUNT(*) as total_users,
AVG(CASE WHEN onboarding_completed THEN 1 ELSE 0 END) as onboarding_completion_rate,
AVG(time_to_first_activity_minutes) as avg_time_to_value
FROM users
WHERE created_at >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY acquisition_channel;
```
### 2. Engagement Metrics
#### Daily Active Users (DAU) / Monthly Active Users (MAU)
```typescript
// Analytics service tracking
export interface EngagementMetrics {
dau: number; // Users active in last 24h
wau: number; // Users active in last 7 days
mau: number; // Users active in last 30 days
dauMauRatio: number; // Stickiness: DAU/MAU (target: >20%)
averageSessionDuration: number; // Minutes (target: >5 min)
sessionsPerUser: number; // Per day (target: >2)
}
```
**Dashboard Queries**:
```sql
-- DAU/WAU/MAU trend
WITH daily_users AS (
SELECT
DATE(last_active_at) as date,
user_id
FROM user_sessions
WHERE last_active_at >= CURRENT_DATE - INTERVAL '30 days'
)
SELECT
date,
COUNT(DISTINCT user_id) as dau,
COUNT(DISTINCT user_id) FILTER (
WHERE date >= CURRENT_DATE - INTERVAL '7 days'
) OVER () as wau,
COUNT(DISTINCT user_id) OVER () as mau,
ROUND(COUNT(DISTINCT user_id)::numeric /
NULLIF(COUNT(DISTINCT user_id) OVER (), 0) * 100, 2) as dau_mau_ratio
FROM daily_users
GROUP BY date
ORDER BY date DESC;
-- Power users (top 20% by activity)
SELECT
user_id,
COUNT(*) as total_activities,
COUNT(DISTINCT DATE(created_at)) as active_days,
AVG(session_duration_seconds) / 60 as avg_session_minutes
FROM activities
WHERE created_at >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY user_id
HAVING COUNT(*) > (
SELECT PERCENTILE_CONT(0.8) WITHIN GROUP (ORDER BY activity_count)
FROM (SELECT COUNT(*) as activity_count FROM activities GROUP BY user_id) counts
)
ORDER BY total_activities DESC;
```
#### Feature Adoption
```typescript
export interface FeatureAdoption {
feature: string;
totalUsers: number;
adoptionRate: number; // % of total users
timeToAdoption: number; // Days since signup
retentionAfterAdoption: number; // % still using after 7 days
}
// Target adoption rates:
const targetAdoption = {
activityTracking: 0.95, // 95% core feature
aiAssistant: 0.70, // 70% AI engagement
voiceInput: 0.40, // 40% voice adoption
familySharing: 0.60, // 60% multi-user
analytics: 0.80, // 80% view insights
exportReports: 0.25, // 25% premium feature
};
```
**Dashboard Queries**:
```sql
-- Feature adoption over time
SELECT
feature_name,
COUNT(DISTINCT user_id) as users,
COUNT(DISTINCT user_id)::float /
(SELECT COUNT(*) FROM users WHERE created_at <= CURRENT_DATE) as adoption_rate,
AVG(EXTRACT(DAY FROM first_use_at - u.created_at)) as avg_days_to_adoption
FROM feature_usage fu
JOIN users u ON fu.user_id = u.id
WHERE fu.first_use_at >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY feature_name
ORDER BY adoption_rate DESC;
```
### 3. Retention Metrics
#### Cohort Retention Analysis
```typescript
export interface CohortRetention {
cohort: string; // e.g., "2025-01-W1"
day0: number; // 100% (signup)
day1: number; // Target: >40%
day7: number; // Target: >60%
day30: number; // Target: >40%
day90: number; // Target: >30%
}
```
**Dashboard Queries**:
```sql
-- Weekly cohort retention
WITH cohorts AS (
SELECT
user_id,
DATE_TRUNC('week', created_at) as cohort_week
FROM users
),
retention AS (
SELECT
c.cohort_week,
COUNT(DISTINCT c.user_id) as cohort_size,
COUNT(DISTINCT CASE
WHEN DATE(s.last_active_at) = DATE(c.cohort_week)
THEN s.user_id
END) as day0,
COUNT(DISTINCT CASE
WHEN DATE(s.last_active_at) = DATE(c.cohort_week) + INTERVAL '1 day'
THEN s.user_id
END) as day1,
COUNT(DISTINCT CASE
WHEN DATE(s.last_active_at) BETWEEN
DATE(c.cohort_week) AND DATE(c.cohort_week) + INTERVAL '7 days'
THEN s.user_id
END) as day7,
COUNT(DISTINCT CASE
WHEN DATE(s.last_active_at) BETWEEN
DATE(c.cohort_week) AND DATE(c.cohort_week) + INTERVAL '30 days'
THEN s.user_id
END) as day30
FROM cohorts c
LEFT JOIN user_sessions s ON c.user_id = s.user_id
GROUP BY c.cohort_week
)
SELECT
cohort_week,
cohort_size,
ROUND(day0::numeric / cohort_size * 100, 2) as day0_retention,
ROUND(day1::numeric / cohort_size * 100, 2) as day1_retention,
ROUND(day7::numeric / cohort_size * 100, 2) as day7_retention,
ROUND(day30::numeric / cohort_size * 100, 2) as day30_retention
FROM retention
ORDER BY cohort_week DESC;
```
### 4. Monetization Metrics
#### Conversion & Revenue
```typescript
export interface MonetizationMetrics {
// Trial & Subscription
trialStarts: number;
trialToPayingConversion: number; // Target: >30%
churnRate: number; // Target: <5% monthly
// Revenue
mrr: number; // Monthly Recurring Revenue
arpu: number; // Average Revenue Per User
ltv: number; // Lifetime Value
cac: number; // Customer Acquisition Cost
ltvCacRatio: number; // Target: >3
// Pricing tiers
premiumSubscribers: number;
premiumAdoptionRate: number; // % of active users
}
```
**Dashboard Queries**:
```sql
-- MRR trend and growth
SELECT
DATE_TRUNC('month', subscription_start_date) as month,
COUNT(*) as new_subscriptions,
COUNT(*) FILTER (WHERE previous_subscription_id IS NOT NULL) as upgrades,
COUNT(*) FILTER (WHERE subscription_end_date IS NOT NULL) as churned,
SUM(price) as mrr,
LAG(SUM(price)) OVER (ORDER BY DATE_TRUNC('month', subscription_start_date)) as previous_mrr,
ROUND((SUM(price) - LAG(SUM(price)) OVER (ORDER BY DATE_TRUNC('month', subscription_start_date))) /
NULLIF(LAG(SUM(price)) OVER (ORDER BY DATE_TRUNC('month', subscription_start_date)), 0) * 100, 2
) as mrr_growth_rate
FROM subscriptions
GROUP BY month
ORDER BY month DESC;
-- LTV calculation
WITH user_revenue AS (
SELECT
user_id,
SUM(amount) as total_revenue,
MIN(payment_date) as first_payment,
MAX(payment_date) as last_payment,
COUNT(*) as payment_count
FROM payments
WHERE status = 'completed'
GROUP BY user_id
)
SELECT
AVG(total_revenue) as avg_ltv,
PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY total_revenue) as median_ltv,
AVG(EXTRACT(DAY FROM last_payment - first_payment)) as avg_lifetime_days
FROM user_revenue;
-- Churn analysis
SELECT
DATE_TRUNC('month', cancelled_at) as month,
COUNT(*) as churned_users,
AVG(EXTRACT(DAY FROM cancelled_at - subscription_start_date)) as avg_days_before_churn,
cancellation_reason,
COUNT(*) FILTER (WHERE cancellation_reason IS NOT NULL) as reason_count
FROM subscriptions
WHERE cancelled_at IS NOT NULL
GROUP BY month, cancellation_reason
ORDER BY month DESC, reason_count DESC;
```
### 5. Product Quality Metrics
#### Technical Health
```typescript
export interface QualityMetrics {
// Performance
apiResponseTimeP95: number; // Target: <2s
apiResponseTimeP99: number; // Target: <3s
errorRate: number; // Target: <1%
// Reliability
uptime: number; // Target: >99.9%
crashFreeUsers: number; // Target: >98%
crashFreeS essions: number; // Target: >99.5%
// User satisfaction
appStoreRating: number; // Target: >4.0
nps: number; // Net Promoter Score (target: >50)
csat: number; // Customer Satisfaction (target: >80%)
}
```
**Dashboard Queries**:
```sql
-- API performance monitoring
SELECT
DATE_TRUNC('hour', timestamp) as hour,
endpoint,
COUNT(*) as request_count,
ROUND(AVG(response_time_ms), 2) as avg_response_time,
PERCENTILE_CONT(0.95) WITHIN GROUP (ORDER BY response_time_ms) as p95_response_time,
PERCENTILE_CONT(0.99) WITHIN GROUP (ORDER BY response_time_ms) as p99_response_time,
COUNT(*) FILTER (WHERE status_code >= 500) as server_errors,
COUNT(*) FILTER (WHERE status_code >= 400 AND status_code < 500) as client_errors
FROM api_logs
WHERE timestamp >= NOW() - INTERVAL '24 hours'
GROUP BY hour, endpoint
HAVING COUNT(*) > 100 -- Only endpoints with significant traffic
ORDER BY hour DESC, p99_response_time DESC;
-- Crash analytics
SELECT
DATE(created_at) as date,
platform,
app_version,
COUNT(DISTINCT user_id) as affected_users,
COUNT(*) as crash_count,
error_message,
stack_trace
FROM error_logs
WHERE severity = 'fatal'
AND created_at >= CURRENT_DATE - INTERVAL '7 days'
GROUP BY date, platform, app_version, error_message, stack_trace
ORDER BY affected_users DESC;
```
---
## Analytics Dashboard Templates
### 1. Executive Dashboard (Daily Review)
**Key Metrics Card Layout**:
```
┌─────────────────────────────────────────────────────┐
│ Daily Active Users │ MRR │ Uptime │
│ 5,234 ↑ 12% │ $12,450 ↑ 8% │ 99.98% │
├─────────────────────────────────────────────────────┤
│ New Signups │ Churn Rate │ NPS │
│ 342 ↑ 5% │ 4.2% ↓ 0.3% │ 62 ↑ 3 │
└─────────────────────────────────────────────────────┘
📊 7-Day User Growth Trend
[Line chart: DAU over time]
📊 Feature Adoption (Last 7 Days)
[Bar chart: % of users by feature]
🚨 Alerts & Issues
• P95 response time elevated (2.3s, target: 2.0s)
• Crash rate on Android 1.2.0 (3.1%, target: <2%)
```
### 2. Product Analytics Dashboard
**User Journey Funnel**:
```sql
-- Onboarding funnel conversion
SELECT
'App Download' as step,
1 as step_number,
COUNT(*) as users,
100.0 as conversion_rate
FROM downloads
WHERE created_at >= CURRENT_DATE - INTERVAL '7 days'
UNION ALL
SELECT
'Registration Started' as step,
2,
COUNT(*),
ROUND(COUNT(*)::numeric / (SELECT COUNT(*) FROM downloads WHERE created_at >= CURRENT_DATE - INTERVAL '7 days') * 100, 2)
FROM users
WHERE created_at >= CURRENT_DATE - INTERVAL '7 days'
UNION ALL
SELECT
'Onboarding Completed' as step,
3,
COUNT(*),
ROUND(COUNT(*)::numeric / (SELECT COUNT(*) FROM downloads WHERE created_at >= CURRENT_DATE - INTERVAL '7 days') * 100, 2)
FROM users
WHERE onboarding_completed_at IS NOT NULL
AND created_at >= CURRENT_DATE - INTERVAL '7 days'
UNION ALL
SELECT
'First Activity Logged' as step,
4,
COUNT(DISTINCT user_id),
ROUND(COUNT(DISTINCT user_id)::numeric / (SELECT COUNT(*) FROM downloads WHERE created_at >= CURRENT_DATE - INTERVAL '7 days') * 100, 2)
FROM activities
WHERE created_at >= CURRENT_DATE - INTERVAL '7 days'
AND created_at <= (SELECT created_at FROM users WHERE user_id = activities.user_id) + INTERVAL '24 hours'
ORDER BY step_number;
```
**User Segmentation**:
```typescript
export enum UserSegment {
NEW_USER = 'new_user', // < 7 days
ENGAGED = 'engaged', // 3+ activities/day
AT_RISK = 'at_risk', // No activity in 7 days
POWER_USER = 'power_user', // Top 20% by activity
PREMIUM = 'premium', // Paid subscription
CHURNED = 'churned', // No activity in 30 days
}
// Segment users for targeted interventions
const segments = {
new_user: {
criteria: 'days_since_signup < 7',
action: 'Send onboarding emails',
},
engaged: {
criteria: 'activities_per_day >= 3',
action: 'Upsell premium features',
},
at_risk: {
criteria: 'days_since_last_activity >= 7 AND < 30',
action: 'Re-engagement campaign',
},
churned: {
criteria: 'days_since_last_activity >= 30',
action: 'Win-back campaign',
},
};
```
### 3. A/B Testing Dashboard
**Experiment Tracking**:
```typescript
export interface ABTest {
id: string;
name: string;
hypothesis: string;
variants: {
control: {
users: number;
conversionRate: number;
};
variant: {
users: number;
conversionRate: number;
};
};
pValue: number; // Statistical significance
winner?: 'control' | 'variant';
status: 'running' | 'completed' | 'cancelled';
}
// Example: Test new onboarding flow
const onboardingTest: ABTest = {
id: 'exp_001',
name: 'New Onboarding Flow',
hypothesis: 'Simplified 3-step onboarding will increase completion rate from 75% to 85%',
variants: {
control: {
users: 1000,
conversionRate: 0.75,
},
variant: {
users: 1000,
conversionRate: 0.82,
},
},
pValue: 0.03, // Statistically significant (< 0.05)
winner: 'variant',
status: 'completed',
};
```
**Dashboard Queries**:
```sql
-- A/B test results
WITH test_users AS (
SELECT
experiment_id,
variant,
user_id,
CASE WHEN action_completed THEN 1 ELSE 0 END as converted
FROM ab_test_assignments
WHERE experiment_id = 'exp_001'
)
SELECT
variant,
COUNT(*) as total_users,
SUM(converted) as conversions,
ROUND(AVG(converted) * 100, 2) as conversion_rate,
ROUND(STDDEV(converted), 4) as std_dev
FROM test_users
GROUP BY variant;
-- Calculate statistical significance (chi-square test)
-- Use external tool or statistics library
```
---
## Monitoring & Alerting
### Alert Rules
**Critical Alerts** (PagerDuty/Slack)
```yaml
alerts:
- name: "High Error Rate"
condition: "error_rate > 5%"
window: "5 minutes"
severity: "critical"
notification: "pagerduty"
- name: "API Response Time Degradation"
condition: "p95_response_time > 3s"
window: "10 minutes"
severity: "high"
notification: "slack"
- name: "Database Connection Pool Exhausted"
condition: "active_connections >= 95% of pool_size"
window: "1 minute"
severity: "critical"
notification: "pagerduty"
- name: "Crash Rate Spike"
condition: "crash_rate > 2%"
window: "1 hour"
severity: "high"
notification: "slack"
```
**Business Alerts** (Email/Slack)
```yaml
alerts:
- name: "Daily Active Users Drop"
condition: "today_dau < yesterday_dau * 0.8"
window: "daily"
severity: "medium"
notification: "email"
- name: "Churn Rate Increase"
condition: "monthly_churn > 7%"
window: "weekly"
severity: "medium"
notification: "slack"
- name: "Low Onboarding Completion"
condition: "onboarding_completion_rate < 80%"
window: "daily"
severity: "low"
notification: "email"
```
---
## Rapid Iteration Framework
### Week 1-2 Post-Launch: Monitoring & Triage
```markdown
**Focus**: Identify and fix critical issues
Daily Tasks:
- [ ] Review crash reports (target: <2%)
- [ ] Check error logs and API failures
- [ ] Monitor onboarding completion rate (target: >90%)
- [ ] Track day-1 retention (target: >40%)
Weekly Review:
- Analyze user feedback from in-app surveys
- Identify top 3 pain points
- Prioritize bug fixes vs. feature requests
- Plan hotfix releases if needed
```
### Week 3-4: Optimization
```markdown
**Focus**: Improve core metrics
Experiments to Run:
1. A/B test onboarding flow variations
2. Test different push notification timings
3. Optimize AI response quality
4. Improve activity tracking UX
Success Metrics:
- Increase day-7 retention to 60%
- Increase AI assistant usage to 70%
- Reduce time-to-first-value to <2 minutes
```
### Month 2: Feature Iteration
```markdown
**Focus**: Expand value proposition
Based on Data:
- Identify most-used features (double down)
- Identify least-used features (improve or remove)
- Analyze user segments (power users vs. casual)
- Test premium feature adoption
New Features to Test:
- Sleep coaching (if sleep tracking is popular)
- Meal planning (if feeding tracking is high-engagement)
- Community forums (if users request social features)
```
---
## Tools & Integration
### Recommended Analytics Stack
**Core Analytics**: PostHog (open-source, self-hosted)
```typescript
// Backend integration
import { PostHog } from 'posthog-node';
const posthog = new PostHog(
process.env.POSTHOG_API_KEY,
{ host: 'https://app.posthog.com' }
);
// Track events
posthog.capture({
distinctId: userId,
event: 'activity_logged',
properties: {
type: 'feeding',
method: 'voice',
},
});
// User properties
posthog.identify({
distinctId: userId,
properties: {
email: user.email,
isPremium: subscription.isPremium,
familySize: family.members.length,
},
});
```
**Error Tracking**: Sentry
```typescript
import * as Sentry from '@sentry/node';
Sentry.init({
dsn: process.env.SENTRY_DSN,
environment: process.env.NODE_ENV,
tracesSampleRate: 1.0,
});
// Automatic error capture
// Manual events
Sentry.captureMessage('User encountered issue', 'warning');
```
**Uptime Monitoring**: UptimeRobot / Pingdom
```yaml
checks:
- name: "API Health"
url: "https://api.maternalapp.com/health"
interval: "1 minute"
- name: "Web App"
url: "https://app.maternalapp.com"
interval: "1 minute"
```
**Performance**: Grafana + Prometheus
```yaml
# prometheus.yml
scrape_configs:
- job_name: 'maternal-app-backend'
static_configs:
- targets: ['localhost:3000/metrics']
```
---
## Conclusion
This analytics framework enables:
1. **Data-Driven Decisions**: Track what matters
2. **Rapid Iteration**: Identify and fix issues quickly
3. **User Understanding**: Segment and personalize
4. **Business Growth**: Monitor revenue and churn
5. **Product Quality**: Maintain high standards
Review dashboards daily, iterate weekly, and adjust strategy monthly based on real-world usage data.

View File

@@ -1,291 +0,0 @@
# PWA Web Push (Local, Apprise) — MVP Implementation Plan
**Goal:** Ship a fully local/browser-push MVP (no Firebase). Frontend collects Web Push subscriptions (VAPID); backend stores and routes; a local dispatcher sends notifications via **Apprise** (`vapid://`). Optional Kafka for decoupling.
---
## Phase 0 — Foundations & Decisions (1 day)
**Outcomes**
- PWA target browsers: Chrome/Edge/Firefox (desktop/mobile), Safari iOS 16.4+ (installed PWA).
- Tech choices:
- Frontend: existing web app + Service Worker.
- Backend: **FastAPI (Python)** or **Node/Express** (pick one).
- Dispatcher: Python + Apprise.
- Storage: Postgres (or SQLite for dev).
- Messaging (optional but recommended): Kafka (local), else direct HTTP call.
- Domain + TLS (required for Push): HTTPS everywhere.
**Deliverables**
- `.env.example` (VAPID\_PRIVATE\_KEY\_PATH, VAPID\_PUBLIC\_KEY, DB\_URL, KAFKA\_BROKERS, APPRISE\_STORAGE\_PATH).
- VAPID keypair generated.
```bash
# Example: generate VAPID keys (node-web-push)
npx web-push generate-vapid-keys
# save PUBLIC / PRIVATE into secure storage or PEM files
```
---
## Phase 1 — PWA Frontend (Service Worker & Subscription) (0.51 day)
**Tasks**
- Register Service Worker: `sw.js`.
- Permission flow: `Notification.requestPermission()` + feature checks.
- Subscribe user: `registration.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: VAPID_PUBLIC })`.
- Send `subscription` JSON to backend; handle revoke/refresh.
**Minimal code (TypeScript/JS)**
```js
// app-push.ts
export async function ensurePushSubscription(vapidPublicKey) {
if (!('serviceWorker' in navigator) || !('PushManager' in window)) return null;
const reg = await navigator.serviceWorker.register('/sw.js');
const perm = await Notification.requestPermission();
if (perm !== 'granted') return null;
const sub = await reg.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(vapidPublicKey),
});
// POST to backend
await fetch('/api/push/subscriptions', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(sub) });
return sub;
}
```
**Service Worker**
```js
// sw.js
self.addEventListener('push', event => {
const data = event.data ? event.data.json() : {};
event.waitUntil(self.registration.showNotification(data.title || 'Notification', {
body: data.body,
icon: data.icon,
badge: data.badge,
data: data.data,
tag: data.tag, // collapseId equivalent
requireInteraction: !!data.requireInteraction,
}));
});
self.addEventListener('notificationclick', event => {
event.notification.close();
const url = event.notification.data?.url || '/';
event.waitUntil(clients.openWindow(url));
});
```
---
## Phase 2 — Backend Subscription API & Storage (0.5 day)
**Tables (Postgres)**
```sql
create table push_subscriptions (
id uuid primary key default gen_random_uuid(),
user_id uuid not null,
endpoint text not null unique,
p256dh text not null,
auth text not null,
ua text,
created_at timestamptz default now(),
updated_at timestamptz default now(),
last_status int,
active boolean default true
);
create index on push_subscriptions(user_id);
```
**HTTP API**
- `POST /api/push/subscriptions` — upsert subscription (by `endpoint`).
- `DELETE /api/push/subscriptions/:id` — deactivate.
- `GET /api/push/subscriptions/me` — list current users subs.
**Validation**: ensure `endpoint`, `keys.p256dh`, `keys.auth` present.
---
## Phase 3 — Message Contract & Routing (0.5 day)
**Unified message (Kafka or HTTP)**
```json
{
"user_id": "uuid",
"channels": ["webpush"],
"webpush": {
"title": "ParentFlow",
"body": "Reminder: feeding due",
"icon": "/icons/app.png",
"badge": "/icons/badge.png",
"tag": "timeline-123",
"data": { "url": "/timeline/123" }
},
"dedupe_key": "timeline-123",
"ttl_seconds": 3600,
"priority": "normal"
}
```
**Routing**
- App publishes message per user/segment → Kafka topic `notify.events` (or POST `/api/push/send`).
- Dispatcher consumes and fans out to each active subscription for that user.
---
## Phase 4 — Local Dispatcher (Python + Apprise) (1 day)
**Responsibilities**
- Consume messages (Kafka) or receive HTTP.
- Load active subscriptions for `user_id`.
- For each subscription → invoke Apprise `vapid://` with per-subscription `subfile` data.
- Update delivery result (`last_status`, deactivate on 404/410).
**Apprise usage (per send)**
```python
import apprise, json, tempfile
ap = apprise.Apprise()
# write subscription JSON to a temp file (or pass inline as data URI)
subfile = tempfile.NamedTemporaryFile(delete=False)
subfile.write(json.dumps(subscription).encode()); subfile.flush()
ap.add(
f"vapid://{MAILTO_IDENT}/{subscription['endpoint']}?"
f"keyfile={VAPID_PRIVATE_KEY_PATH}&subfile={subfile.name}"
)
ap.notify(title=msg['webpush']['title'], body=msg['webpush']['body'])
```
**Failures handling**
- HTTP 404/410 → mark `active=false`.
- 429/5xx → exponential backoff (retry queue with max attempts).
**Performance**
- Batch fan-out with worker pool (e.g., `concurrent.futures.ThreadPoolExecutor`).
- Keep Apprise in-memory; enable persistent storage `AUTO` for token caching.
---
## Phase 5 — Admin & Lifecycle (0.5 day)
- Subscription pruning cron: deactivate stale (`updated_at < now()-90d`) or failed endpoints.
- Unsubscribe endpoint (user action) → delete/deactivate.
- Privacy: per-user export & hard delete subscriptions on request.
---
## Phase 6 — Observability (0.5 day)
- Structured logs (JSON) for send attempts with `endpoint_hash` only (no PII).
- Metrics: sends, success rate, failures by code, active subs, opt-in rate.
- Dashboards: Grafana/Prometheus (optional) or simple SQL views.
---
## Phase 7 — Security & Compliance (0.5 day)
- Store VAPID private key on disk with strict permissions or in a local vault.
- HTTPS only; set `Strict-Transport-Security`.
- CSRF for subscription endpoints; auth required.
- Rate limit `/api/push/subscriptions` + `/api/push/send`.
- Content rules: cap payload size (<4KB), sanitize URLs.
---
## Phase 8 — iOS/Safari Specifics (notes)
- Web Push works for **installed** PWA only (Add to Home Screen).
- Permission must be user-gesture initiated.
- Background delivery may be throttled; design for non-guaranteed delivery.
---
## Phase 9 — Testing & Load (0.51 day)
- Unit: subscription CRUD, dispatcher send mock.
- E2E: subscribe → send → receive across browsers.
- Load: N users × M subs; verify throughput and backoff.
---
## Phase 10 — Rollout & Feature Flags (0.5 day)
- Feature flag `webpush_enabled` per user/tenant.
- Gradual rollout: 5% → 25% → 100%.
- Fallback channel (email/Telegram via Apprise) if webpush not available.
---
## Upgrade Path — Firebase/OneSignal (when needed)
- Abstract `Notifier` with drivers: `webpush_vapid`, `fcm`, `onesignal`.
- Mirror message schema; add provider-specific fields.
- Migration: dual-write for 12 weeks, compare delivery metrics, then switch.
---
## Acceptance Criteria
- Users can opt-in, receive a test notification within 3s median on desktop Chrome.
- Subscriptions are persisted and deduplicated by `endpoint`.
- Dead endpoints are auto-pruned on 404/410 within 24h.
- No VAPID private keys leak in logs; payload ≤ 4KB; HTTPS enforced.
---
## Quick Reference (Snippets)
**VAPID env**
```ini
VAPID_PUBLIC_KEY=...
VAPID_PRIVATE_KEY_PATH=/secrets/vapid_private_key.pem
MAILTO_IDENT=push@yourdomain.com
```
**HTTP publish (no Kafka) — example contract**
```http
POST /api/push/send
Content-Type: application/json
{ "user_id": "...", "webpush": { "title": "Hi", "body": "", "data": {"url":"/"} } }
```
**Kafka topics (optional)**
- `notify.events` (ingress)
- `notify.retry` (backoff)
- `notify.deadletter`
---
## Risks & Mitigations
- **Browser variability** → test matrix; graceful degradation.
- **Quota / payload limits** → compact payloads; use `tag` to collapse duplicates.
- **No delivery guarantees** → show in-app inbox as source of truth.
---
## Done Means
- End-to-end working on Chrome desktop + Android Chrome.
- At least 1 iOS PWA device validated.
- Metrics panel shows ≥95% success on active endpoints over 48h.

View File

@@ -1,259 +0,0 @@
#!/bin/bash
# ParentFlow Development Servers Start Script
# Starts all development servers on 0.0.0.0 for external access
set -e
# Color codes for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
# Logging functions
log() {
echo -e "${BLUE}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $1"
}
error() {
echo -e "${RED}[ERROR]${NC} $1" >&2
exit 1
}
success() {
echo -e "${GREEN}${NC} $1"
}
warning() {
echo -e "${YELLOW}${NC} $1"
}
# Header
echo ""
echo "============================================"
echo " ParentFlow Development Servers v1.0 "
echo "============================================"
echo ""
# Function to kill processes on a port - more aggressive
kill_port() {
local PORT=$1
local SERVICE=$2
log "Forcefully clearing port $PORT ($SERVICE)..."
# Method 1: Using lsof
if command -v lsof &> /dev/null; then
local PIDS=$(lsof -t -i:$PORT 2>/dev/null || true)
if [ -n "$PIDS" ]; then
warning "Found PIDs on port $PORT: $PIDS"
echo $PIDS | xargs -r kill -9 2>/dev/null || true
sleep 1
fi
fi
# Method 2: Using fuser as fallback
fuser -k $PORT/tcp 2>/dev/null || true
sleep 1
# Method 3: Kill any process with the port in its command
pkill -f ":$PORT" 2>/dev/null || true
pkill -f "PORT=$PORT" 2>/dev/null || true
sleep 1
# Method 4: Using netstat/ss to find and kill
if command -v ss &> /dev/null; then
local PIDS=$(ss -tulpn 2>/dev/null | grep ":$PORT " | grep -oP 'pid=\K[0-9]+' || true)
if [ -n "$PIDS" ]; then
echo $PIDS | xargs -r kill -9 2>/dev/null || true
sleep 1
fi
fi
# Final aggressive cleanup - kill anything that might be related
pkill -f "npm.*dev.*$PORT" 2>/dev/null || true
pkill -f "node.*$PORT" 2>/dev/null || true
pkill -f "next.*$PORT" 2>/dev/null || true
sleep 1
# Verify the port is free
if lsof -i:$PORT > /dev/null 2>&1; then
error "Failed to clear port $PORT after multiple attempts. Please run: sudo lsof -i:$PORT and kill -9 <PID>"
else
success "Port $PORT cleared and ready"
fi
}
# Step 0: Kill ALL Node.js dev processes first
log "${CYAN}Step 0: Cleaning up all development processes...${NC}"
# Kill all existing dev servers
pkill -f "npm run dev" 2>/dev/null || true
pkill -f "npm run start:dev" 2>/dev/null || true
pkill -f "next dev" 2>/dev/null || true
pkill -f "node.*dist/main" 2>/dev/null || true
sleep 2
# Now clear the specific ports
log "${CYAN}Clearing specific ports...${NC}"
kill_port 3020 "Backend API"
kill_port 3030 "Frontend"
kill_port 3335 "Admin Dashboard"
# Verify Node.js is installed
if ! command -v node &> /dev/null; then
error "Node.js is not installed. Please install Node.js first."
fi
# Verify npm is installed
if ! command -v npm &> /dev/null; then
error "npm is not installed. Please install npm first."
fi
# Step 1: Start Backend Development Server
log "${CYAN}Step 1: Starting Backend API on 0.0.0.0:3020...${NC}"
cd /root/maternal-app/maternal-app/maternal-app-backend
# Check if dependencies are installed
if [ ! -d "node_modules" ]; then
warning "Backend dependencies not found, installing..."
npm install
fi
# Start backend in background
npm run start:dev > /tmp/backend-dev.log 2>&1 &
BACKEND_PID=$!
echo $BACKEND_PID > /tmp/backend-dev.pid
success "Backend API started (PID: $BACKEND_PID)"
log "Backend accessible at: http://maternal-api.noru1.ro (0.0.0.0:3020)"
# Step 2: Start Frontend Development Server
log "${CYAN}Step 2: Starting Frontend on 0.0.0.0:3030...${NC}"
cd /root/maternal-app/maternal-web
# Check if dependencies are installed
if [ ! -d "node_modules" ]; then
warning "Frontend dependencies not found, installing..."
npm install
fi
# Create .env.local if it doesn't exist
if [ ! -f ".env.local" ]; then
cat > .env.local << EOF
NEXT_PUBLIC_API_URL=https://maternal-api.noru1.ro
NEXT_PUBLIC_GRAPHQL_URL=https://maternal-api.noru1.ro/graphql
NEXT_PUBLIC_WS_URL=wss://maternal-api.noru1.ro
NEXT_PUBLIC_APP_URL=https://maternal.noru1.ro
NEXT_PUBLIC_APP_NAME=ParentFlow
EOF
log "Created .env.local for frontend"
fi
# Start frontend in background using full path to next
node_modules/next/dist/bin/next dev -p 3030 -H 0.0.0.0 > /tmp/frontend-dev.log 2>&1 &
FRONTEND_PID=$!
echo $FRONTEND_PID > /tmp/frontend-dev.pid
success "Frontend started (PID: $FRONTEND_PID)"
log "Frontend accessible at: http://maternal.noru1.ro (0.0.0.0:3030)"
# Step 3: Start Admin Dashboard Development Server
log "${CYAN}Step 3: Starting Admin Dashboard on 0.0.0.0:3335...${NC}"
cd /root/maternal-app/parentflow-admin
# Check if dependencies are installed
if [ ! -d "node_modules" ]; then
warning "Admin dependencies not found, installing..."
npm install
fi
# Create .env.local if it doesn't exist
if [ ! -f ".env.local" ]; then
cat > .env.local << EOF
NEXT_PUBLIC_API_URL=https://maternal-api.noru1.ro
NEXT_PUBLIC_APP_URL=https://pfadmin.noru1.ro
NEXT_PUBLIC_APP_NAME=ParentFlow Admin
EOF
log "Created .env.local for admin dashboard"
fi
# Start admin dashboard in background using full path to next
node_modules/next/dist/bin/next dev -p 3335 -H 0.0.0.0 > /tmp/admin-dev.log 2>&1 &
ADMIN_PID=$!
echo $ADMIN_PID > /tmp/admin-dev.pid
success "Admin Dashboard started (PID: $ADMIN_PID)"
log "Admin accessible at: http://pfadmin.noru1.ro (0.0.0.0:3335)"
# Step 4: Verify all services are running
log "${CYAN}Step 4: Verifying services...${NC}"
log "Waiting 60 seconds for services to start..."
sleep 60
verify_service() {
local SERVICE=$1
local PORT=$2
local PID_FILE=$3
# Check if port is listening
if ss -tulpn | grep -q ":$PORT.*LISTEN"; then
success "$SERVICE is listening on port $PORT"
return 0
else
# Check if process is still starting
if [ -f "$PID_FILE" ]; then
PID=$(cat $PID_FILE)
if kill -0 $PID 2>/dev/null; then
warning "$SERVICE is running (PID: $PID) but not yet listening on port $PORT"
return 1
else
error "$SERVICE process (PID: $PID) died. Check logs: tail -50 /tmp/${SERVICE,,}-dev.log"
return 1
fi
else
warning "$SERVICE PID file not found"
return 1
fi
fi
}
ALL_GOOD=true
verify_service "Backend API" 3020 /tmp/backend-dev.pid || ALL_GOOD=false
verify_service "Frontend" 3030 /tmp/frontend-dev.pid || ALL_GOOD=false
verify_service "Admin Dashboard" 3335 /tmp/admin-dev.pid || ALL_GOOD=false
# Final summary
echo ""
echo "============================================"
if [ "$ALL_GOOD" = true ]; then
echo -e "${GREEN} All Development Servers Started! ${NC}"
else
echo -e "${YELLOW} Some Services Failed to Start ${NC}"
fi
echo "============================================"
echo ""
echo "Access URLs:"
echo " Backend API: http://maternal-api.noru1.ro (0.0.0.0:3020)"
echo " Frontend: http://maternal.noru1.ro (0.0.0.0:3030)"
echo " Admin Dashboard: http://pfadmin.noru1.ro (0.0.0.0:3335)"
echo ""
echo "Log files:"
echo " Backend: tail -f /tmp/backend-dev.log"
echo " Frontend: tail -f /tmp/frontend-dev.log"
echo " Admin: tail -f /tmp/admin-dev.log"
echo ""
echo "To stop all servers: ./stop-dev.sh"
echo ""
echo "PID files stored in:"
echo " /tmp/backend-dev.pid"
echo " /tmp/frontend-dev.pid"
echo " /tmp/admin-dev.pid"
echo ""
if [ "$ALL_GOOD" = false ]; then
warning "Check log files for errors"
exit 1
fi
log "Development servers started successfully!"

View File

@@ -1,172 +0,0 @@
#!/bin/bash
# ParentFlow Development Servers Stop Script
# Stops all development servers and cleans up
set -e
# Color codes for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
# Logging functions
log() {
echo -e "${BLUE}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $1"
}
error() {
echo -e "${RED}[ERROR]${NC} $1" >&2
}
success() {
echo -e "${GREEN}${NC} $1"
}
warning() {
echo -e "${YELLOW}${NC} $1"
}
# Header
echo ""
echo "============================================"
echo " Stopping ParentFlow Development Servers "
echo "============================================"
echo ""
# Function to stop a service by PID file
stop_service() {
local SERVICE=$1
local PID_FILE=$2
local PORT=$3
log "Stopping $SERVICE..."
# Try to stop using PID file
if [ -f "$PID_FILE" ]; then
PID=$(cat $PID_FILE)
if kill -0 $PID 2>/dev/null; then
log "Stopping process PID: $PID"
kill -TERM $PID 2>/dev/null || true
sleep 2
# Force kill if still running
if kill -0 $PID 2>/dev/null; then
warning "Process didn't stop gracefully, force killing..."
kill -9 $PID 2>/dev/null || true
fi
rm -f $PID_FILE
success "$SERVICE stopped"
else
warning "$SERVICE process (PID: $PID) was not running"
rm -f $PID_FILE
fi
else
warning "PID file not found for $SERVICE"
fi
# Double-check and kill any remaining processes on the port
if lsof -i:$PORT > /dev/null 2>&1; then
warning "Found process still using port $PORT, killing..."
lsof -t -i:$PORT | xargs -r kill -9 2>/dev/null || true
success "Port $PORT cleared"
fi
}
# Function to kill all Node.js processes matching a pattern
kill_node_pattern() {
local PATTERN=$1
local SERVICE=$2
PIDS=$(ps aux | grep -E "$PATTERN" | grep -v grep | awk '{print $2}' || true)
if [ -n "$PIDS" ]; then
warning "Found $SERVICE processes: $PIDS"
echo $PIDS | xargs -r kill -9 2>/dev/null || true
success "$SERVICE processes killed"
fi
}
# Step 1: Stop Backend API
log "${CYAN}Step 1: Stopping Backend API...${NC}"
stop_service "Backend API" "/tmp/backend-dev.pid" 3020
kill_node_pattern "npm.*start:dev.*3020" "Backend"
kill_node_pattern "node.*dist/main.*3020" "Backend"
# Step 2: Stop Frontend
log "${CYAN}Step 2: Stopping Frontend...${NC}"
stop_service "Frontend" "/tmp/frontend-dev.pid" 3030
kill_node_pattern "npm.*dev.*3030" "Frontend"
kill_node_pattern "next.*dev.*3030" "Frontend"
# Step 3: Stop Admin Dashboard
log "${CYAN}Step 3: Stopping Admin Dashboard...${NC}"
stop_service "Admin Dashboard" "/tmp/admin-dev.pid" 3335
kill_node_pattern "npm.*dev.*3335" "Admin"
kill_node_pattern "next.*dev.*3335" "Admin"
# Step 4: Clean up log files
log "${CYAN}Step 4: Cleaning up...${NC}"
if [ -f "/tmp/backend-dev.log" ]; then
rm -f /tmp/backend-dev.log
log "Removed backend log file"
fi
if [ -f "/tmp/frontend-dev.log" ]; then
rm -f /tmp/frontend-dev.log
log "Removed frontend log file"
fi
if [ -f "/tmp/admin-dev.log" ]; then
rm -f /tmp/admin-dev.log
log "Removed admin log file"
fi
# Step 5: Final port check
log "${CYAN}Step 5: Verifying ports are free...${NC}"
check_port() {
local PORT=$1
local SERVICE=$2
if lsof -i:$PORT > /dev/null 2>&1; then
error "Port $PORT is still in use ($SERVICE)"
return 1
else
success "Port $PORT is free ($SERVICE)"
return 0
fi
}
ALL_CLEAR=true
check_port 3020 "Backend API" || ALL_CLEAR=false
check_port 3030 "Frontend" || ALL_CLEAR=false
check_port 3335 "Admin Dashboard" || ALL_CLEAR=false
# Kill any remaining Next.js or npm dev processes
log "${CYAN}Step 6: Cleaning up any remaining dev processes...${NC}"
pkill -f "next dev" 2>/dev/null || true
pkill -f "npm run dev" 2>/dev/null || true
pkill -f "npm run start:dev" 2>/dev/null || true
# Final summary
echo ""
echo "============================================"
if [ "$ALL_CLEAR" = true ]; then
echo -e "${GREEN} All Development Servers Stopped! ${NC}"
else
echo -e "${YELLOW} Some Ports Still In Use ${NC}"
echo ""
echo "Manual cleanup commands:"
echo " lsof -i:3020 | grep LISTEN"
echo " lsof -i:3030 | grep LISTEN"
echo " lsof -i:3335 | grep LISTEN"
echo ""
echo "Force kill all Node processes:"
echo " pkill -9 node"
fi
echo "============================================"
echo ""
log "Development servers stop script completed!"