A privacy-first, sophisticated menstrual cycle & fertility tracker for iOS.
CycleOne is a high-performance, open-source period tracker designed for users who value privacy above all else.
In an era of cloud-connected health apps, CycleOne takes a stand: Your health data is yours alone. Built with a strict "local-only" architecture, it provides professional-grade cycle prediction, symptom tracking, and historical analysis without ever requesting network access, requiring an account, or charging a subscription fee.
| Light Mode | Dark Mode |
|---|---|
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
- Period Projection: Intelligent estimations for start dates and duration based on historical averages.
- Ovulation Tracking: Automatic calculation of ovulation and fertile windows.
- Irregularity Alerts: Identifies significant cycle variances to help you remain aware of physiological shifts.
- Flow Intensity: Categorical tracking from spotting to heavy flow.
- Symptom Database: Track physical, emotional, and digestive indicators.
- Mood & Energy: Document biometric indicators with a streamlined, premium UI.
- Notes: Local-only annotations for detailed record-keeping.
- Native Calendar: Leveraging
UICalendarViewfor a high-contrast, interactive experience. - Dynamic Themes: 5 custom accent color themes (Rose, Lavender, Ocean, Sage, Sunset) to match your style.
- Smooth Animations: High-fidelity transitions and staggered animations for a premium app feel.
- Zero Emojis: A consistent, professional aesthetic using high-quality SF Symbols.
- In-app language switcher in Settings with runtime locale updates.
- Supported languages: English (
en), Filipino/Tagalog (fil), Japanese (ja). - Coverage guardrails: localization parity and source-key coverage tests in
CycleOneTests/LocalizationCoverageTests.swift. - Localized custom pages: Privacy Policy HTML is shipped per language resource bundle.
- Organized resources: language folders are grouped under
CycleOne/LocalizationResources/in source. - Legend correctness: Calendar legend labels resolve localized values (not raw string keys).
- Round-trip stability: UI tests validate language switching Japanese -> English and verify localized legend text remains correct.
Note on folder structure:
- Source files are grouped in
CycleOne/LocalizationResourcesfor maintainability while preserving runtime localization behavior.
CycleOne was built from the ground up to be safe:
- No Cloud Sync: Your data never leaves your device.
- No Accounts: No email, no password, no login required.
- No Analytics: Zero third-party tracking or telemetry.
- No Network Entitlements: The app doesn't even ask for internet permissions.
- Data Sovereignty: Export your entire history to CSV anytime.
| Component | Technology |
|---|---|
| Language | Swift 5.9+ |
| Framework | SwiftUI with MVVM Architecture |
| Logic | Proprietary CycleEngine (Pure Swift) |
| Persistence | Core Data (On-device SQLite) |
| Interface | Native UIKit/SwiftUI hybrid |
| Testing | XCTest (99 tests currently passing in the full suite: 90 unit + 9 UI) |
- macOS 14.0+
- Xcode 15.0+
- SwiftLint & SwiftFormat
- Clone the repo:
git clone https://github.com/VoxDroid/CycleOne.git
- Install pre-commit hooks:
brew install pre-commit pre-commit install
- Open
CycleOne.xcodeprojand build for the simulator.
We use a Makefile for CI/CD consistency:
make check: Full verification suite (Lint, Format, Test, UI Test).make test: Execute the unit-test suite and produceTestResults.xcresultoutput.make test-ui: Execute UI tests only.
DEST_ID=$(xcrun simctl list devices available | awk -F '[()]' '/iPhone/ {print $2; exit}')
if [ -z "$DEST_ID" ]; then
echo "No available iPhone simulator found."
exit 1
fi
xcodebuild test \
-project CycleOne.xcodeproj \
-scheme CycleOne-Unit \
-destination "id=${DEST_ID}" \
-parallel-testing-enabled NO \
-only-testing:CycleOneTests/LocalizationCoverageTests \
-only-testing:CycleOneTests/AppLanguageTestsDEST_ID=$(xcrun simctl list devices available | awk -F '[()]' '/iPhone/ {print $2; exit}')
if [ -z "$DEST_ID" ]; then
echo "No available iPhone simulator found."
exit 1
fi
xcodebuild test \
-project CycleOne.xcodeproj \
-scheme CycleOne-Unit \
-destination "id=${DEST_ID}" \
-parallel-testing-enabled NO \
-only-testing:CycleOneTestsLatest merged local run (UnitCoverage.xcresult + UICoverage.xcresult, 2026-04-08):
CycleOne.app: 10,893 / 10,893 lines (100.00%)CycleOneTests.xctest: 4,298 / 4,316 lines (99.58%)CycleOneUITests.xctest: 955 / 962 lines (99.27%)
Latest run counts:
CycleOneTests.xctest: 182 tests, 0 failures.CycleOneUITests.xctest: 22 tests, 0 failures.
Validation commands executed for this snapshot:
make checkpre-commit run --all-files
Recent reliability/security improvements in this iteration:
- CSV export now escapes quotes, preserves commas safely, and mitigates spreadsheet formula injection (
=,+,-,@prefixes). - Cycle rebuild now logs Core Data fetch/save failures instead of silently swallowing errors.
- Log saving now enforces the Core Data note-length limit (500 chars) to prevent save failures from oversized notes.
We welcome contributions! Please see CONTRIBUTING.md for guidelines on how to get involved.
CycleOne is released under the GNU General Public License v3.0. See LICENSE for details.
Designed and developed by VoxDroid.
© 2026 VoxDroid. All rights reserved.







