Create a fast, private, and intuitive period tracking Progressive Web App (PWA) that empowers young women to understand their reproductive health without compromising their data. All user data is stored exclusively on the user's device.
- Primary: Teenagers and young adults (13-25 years) who are privacy-conscious.
- Experience Level: Mostly beginners to period tracking.
- Current Solutions: Basic health watch tracking, spreadsheets, or no tracking.
- Primary Use Cases: General health awareness, avoiding pregnancy, reproductive health education, private data logging.
- 100% Private: All data is stored locally on your device and never sent to a server.
- Lightning-fast logging: Log your period in under 30 seconds.
- Works entirely offline: No internet connection is required after the initial load.
- Simple, beautiful interface: Designed for a delightful user experience.
- No Account Needed: Start tracking immediately without signing up.
- Frontend: Vite + React SPA + TypeScript + Tanstack router
- Local Database: Dexie.js (a wrapper for IndexedDB)
- State Management: React Query (TanStack Query) for managing local data state, TanStack Store for global state management
- Styling: Tailwind CSS + DaisyUI (Valentine theme), lucide react for icons
- Components: Radix UI (headless components for complex logic), tanstack form for forms, tanstack table for tables
- Project Structure: Modular, Domain-Driven Design
- Validation: Zod schemas for data validation before storage
- Linting: ESLint + ESLint Stylistic
- CI/CD: GitHub Actions, T3Env for typesafe env variables
- Deployment: Cloudflare Pages (static hosting)
- PWA: Service Worker + Web App Manifest
- Testing Storybook (with vitest browser mode)
- Package Management PNPM with corepack and node 24
- Approach: Local-first and local-only. All data is stored and managed in the browser's IndexedDB.
- Type Safety: End-to-end type safety within the client application, from UI components to the local database.
- Offline Strategy: The app is offline by default. No data synchronization is required.
- Data Persistence: Data is persisted across sessions using IndexedDB, managed via Dexie.js.
- Performance Target: < 1 second load times.
The data is structured to clearly separate a period from its daily logs. This allows for efficient querying and a clear representation of user data.
periodsTable: Stores one record for each complete period.id(auto-incrementing primary key)startDate(Date) - The first day of the period.endDate(Date, optional) - The last day of the period. An ongoing period has anullorundefinedendDate.
periodDaysTable: Stores daily logs that belong to a specific period.id(auto-incrementing primary key)periodId(number) - A foreign key referencing theidin theperiodtable.date(Date) - The specific date of the log.flowIntensity(number) - The recorded flow intensity for that day (scale 1-5).
- Use Zod for runtime validation of all data before it's written to the local database.
- Use TanStack Query hooks for fetching, creating, and updating data in the local database.
-
Period Tracking
- Start/stop period logging.
- Flow intensity tracking (1-5 scale).
- Log past periods with start and end dates.
- Calendar and list views of past and current periods.
-
Symptom Logging
- Quick 1-5 scale for: Flow, Mood, Pain, Energy, Bloating, Cravings.
- Optional notes field.
- Medication tracking (free text).
-
Basic Predictions
- Next period start date.
- Cycle length averages.
- Simple confidence indicators based on data consistency.
-
Data Management
- Ability to export all data to a JSON file.
- Ability to import data from a previously exported file.
- A clear "Delete All My Data" button.
- Ability to delete individual periods from the history view.
-
PWA Functionality
- Service worker for instant loading.
- Web App Manifest to allow users to "install" the app on their home screen.
-
Static FAQ
- Common period questions and health education content.
-
Enhanced Analytics
- Cycle pattern analysis.
- Symptom correlation insights.
- Historical comparisons and charts.
-
Fertility Tracking
- Ovulation predictions.
- Fertile window indicators.
- Conception probability estimates.
-
UI Themes
- Allow users to choose from a few different color themes besides the default Valentine theme.
- Minimalist: Clean, uncluttered interface using DaisyUI Valentine theme.
- Fast: Quick interactions, instant feedback.
- Empathetic: Supportive tone, educational, warm color palette.
- Accessible: Radix UI primitives ensure proper accessibility.
- Private: Reassure users their data is safe and local.
- Open app → Auto-loads to today's view.
- One-tap period start/stop.
- Optional: Quick symptom sliders (< 15 seconds).
- Data saves automatically to the local database with visual confirmation.
- Navigate to the "History" or "Calendar" tab.
- See period history and patterns in the preferred view.
- Log a past period via the dedicated button.
- Delete a specific period from the history list.
- View predictions for the next period.
- Initial Load: < 1 second.
- Offline Functionality: 100% of features work offline.
- PWA Score: > 90 on Lighthouse.
Essential infrastructure and basic functionality
Project Setup & Infrastructure
- Initialize Vite + React project with pnpm.
- Set up TypeScript configuration.
- Configure Tailwind CSS + DaisyUI (Valentine theme).
- Configure ESLint + ESLint Stylistic.
- Set up GitHub Actions workflow for CI.
Local Data Persistence
- Set up Dexie.js and define IndexedDB schemas for periods and symptoms.
- Create Zod schemas for all data models.
- Set up React Query client to interact with Dexie.js.
- Implement data access hooks (e.g.,
useCycles,addCycleEntry). - Implement data import/export functionality.
Core Period Tracking
- Build the main UI for period start/stop functionality.
- Build the calendar view component using Radix UI Calendar.
- Implement UI for logging past periods.
- Add a list view for period history with delete functionality.
- Implement period calculation logic.
- Connect UI to local data hooks with comprehensive error handling and loading states.
Core features users need for basic functionality
Symptom Logging Interface
- Create symptom logging interface with DaisyUI sliders.
- Implement 1-5 scale components with optimistic updates.
- Build a daily log view.
- Add notes and medication fields.
Predictions & Basic Analytics
- Implement a simple period prediction algorithm.
- Calculate and display average period length.
- Build prediction display components using DaisyUI cards.
- Implement error handling for insufficient data scenarios.
PWA & Offline Capability
- Implement a service worker with a comprehensive caching strategy.
- Add a web app manifest with theme assets and icons.
- Build UI indicators to encourage users to "install" the app.
- Test PWA functionality across major browsers.
Features that improve the experience but aren't essential for launch
UI/UX Polish & Accessibility
- Implement a cohesive design system with the DaisyUI Valentine theme.
- Ensure responsive design using Tailwind breakpoints.
- Improve accessibility with Radix UI primitives.
- Add loading states, error handling, and user feedback animations.
- Test for keyboard navigation and screen reader compatibility.
Content & Education
- Create static FAQ content.
- Implement an educational section with DaisyUI collapse components.
- Write clear, empathetic error messages and user guidance.
- Build a simple onboarding flow explaining the privacy features.
- App loads in < 1 second.
- PWA score > 90.
- 100% offline functionality is flawless.
- Data persists correctly between sessions.
- Mobile-responsive design works on all major devices.
- Users can log their period in < 30 seconds.
- Predictions are reasonably accurate (within 2-3 days).
- The app feels fast and responsive.
- Users understand and trust the privacy model.
- The interface is intuitive and requires no training.
- Solid understanding of building local-first, privacy-focused PWAs.
- Experience with IndexedDB and libraries like Dexie.js.
- Mastery of state management for local data with React Query.
- Clean, maintainable codebase.
The project will follow a modular, domain-driven structure to ensure a clear separation of concerns and to make the codebase easier to maintain and scale. Logic is grouped by feature/domain rather than by file type.
periodos/
├── src/
│ ├── components/
│ │ └── ui/ # Shared, simple UI components (Button, Card, Input)
│ ├── modules/ # Core application domains (previously `features`)
│ │ ├── periods/ # Domain: Everything related to periods
│ │ │ ├── components/ # React components specific to periods (e.g., CalendarView)
│ │ │ ├── hooks/ # React hooks for periods logic (e.g., useAllPeriods)
│ │ │ ├── types.ts # TypeScript types and Zod schemas for periods
│ │ │ └── index.ts # Public API for the 'periods' module
│ │ ├── symptoms/ # Domain: Everything related to symptom logging
│ │ └── settings/ # Domain: Data import/export, themes, etc.
│ ├── lib/
│ │ └── db.ts # Dexie.js database definition and initialization
│ ├── integrations/ # Integrations with external services/libraries
│ ├── routes/ # Route components for Tanstack Router
│ ├── types/ # Truly global types shared across all domains
│ └── main.tsx # Application entry point
├── public/
├── index.html
├── package.json
├── vite.config.ts
└── tsconfig.json
Module Communication:
- A module (e.g.,
periods) should only expose what is necessary through itsindex.tsfile. - Other parts of the application should only import from a module's public API.
To maintain a clean and readable codebase, the following styles are enforced:
- Import Aliases: Always use non-relative import aliases for modules within the
srcdirectory. Use@/as the prefix for all imports referencing thesrcroot.- Correct:
import { MyComponent } from '@/components/MyComponent'; - Incorrect:
import { MyComponent } from '../../components/MyComponent';
- Correct:
- Primary Feature: All user data is stored exclusively on the user's device in IndexedDB. It is never transmitted to any server.
- Data Control: The user has full control over their data, with clear options for export and deletion.
- Browser Storage Policies: Be aware that some browsers (e.g., Firefox with strict tracking protection) or private/incognito modes may block IndexedDB from being created, leading to a
QuotaExceededError. Using a specific, non-generic database name (e.g.,periodos_dbinstead ofDatabase) is a critical mitigation for this. - Dependencies: Use well-maintained libraries and scan for vulnerabilities.
- HTTPS: The app will be served over HTTPS to protect it in transit from the host to the user.
- Client-Side Performance: Scalability is a matter of client-side performance. Efficient data queries with Dexie.js and optimized React rendering are key.
- Storage Limits: Be mindful of browser storage limits, though they are generous for this type of application. Implement checks if data grows unexpectedly large.
- Clear code documentation and type safety with TypeScript and Zod.
- Automated testing pipeline for core logic (period calculations, data validation).
- Easy, one-command deployment process for the static site.
- Advanced fertility tracking.
- Community features (if a privacy-preserving model can be designed).
- Wearable device integration (via client-side APIs).
- AI-powered insights running locally in the browser (e.g., using TensorFlow.js).
- One-time purchase to unlock "Pro" features (e.g., advanced analytics, themes). This can be managed client-side without a server.
- The app will never monetize by selling user data.
- Explore options for opt-in, end-to-end encrypted data backup/sync using a user's own cloud storage (e.g., Google Drive, iCloud) via file-based import/export.
This PRD serves as the foundation for building a delightful, fast, and reliable period tracking application that prioritizes user privacy and experience above all else.