No description
Find a file
rope bb19bc0aeb Push notifications: period soon/late reminders, test button
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 09:43:41 +01:00
static Push notifications: period soon/late reminders, test button 2026-10-18 09:43:41 +01:00
tests Push notifications: period soon/late reminders, test button 2026-10-18 09:43:41 +01:00
.gitignore Flowtrack: private period tracker with cycle predictions 2026-10-18 08:37:13 +01:00
app.py Push notifications: period soon/late reminders, test button 2026-10-18 09:43:41 +01:00
flake.lock Flowtrack: private period tracker with cycle predictions 2026-10-18 08:37:13 +01:00
flake.nix Push notifications: period soon/late reminders, test button 2026-10-18 09:43:41 +01:00
LICENSE Flowtrack: private period tracker with cycle predictions 2026-10-18 08:37:13 +01:00
module.nix Push notifications: period soon/late reminders, test button 2026-10-18 09:43:41 +01:00
notify.js Push notifications: period soon/late reminders, test button 2026-10-18 09:43:41 +01:00
package.nix Push notifications: period soon/late reminders, test button 2026-10-18 09:43:41 +01:00
README.md Push notifications: period soon/late reminders, test button 2026-10-18 09:43:41 +01:00

Flowtrack

A private, self-hosted period tracker. It logs period days with flow and symptoms, predicts the next six periods, and estimates the fertile window. It installs on a phone home screen as a web app.

The app has no runtime dependencies beyond the Python standard library, and it stores everything in one SQLite file. Nginx and Authelia provide the access boundary.

Predictions

  • Periods are runs of logged period days. Spotting doesn't count, and one missing day inside a run doesn't split it.
  • The cycle length is a weighted average of up to the last 12 cycles, with recent cycles counting more. Cycles shorter than 15 days or longer than 60 are left out because they usually mean a log was missed.
  • Each prediction is a range of ± the cycle's standard deviation (at least 2 days, or 4 with fewer than three cycles). The range widens with √n for later cycles.
  • Ovulation is estimated 14 days before the next period. The fertile window runs from 5 days before ovulation to 1 day after. These are estimates, not contraception.
  • Once the expected day passes, the next period is expected from tomorrow, and later predictions move with it.

The logic lives in static/cycle.js and is tested in tests/test_cycle.js.

Notifications

Web Push, sent by notify.js (Node, no dependencies: built-in crypto and SQLite). It reuses static/cycle.js, so reminders always match the app.

  • flowtrack-notify daily runs once a day. It sends "period expected soon" once per cycle, remindDays (1-7, default 2) before the predicted start, and "period is late" once per cycle after the expected day passes.
  • The owner turns notifications on per device in Settings, where there is also a test button. On iPhone this only works from the Home Screen app (iOS 16.4 or later).
  • The VAPID key pair is created on first start and stored in the database. Replacing it invalidates every subscription.
  • The server only accepts subscriptions on Apple, Google, Mozilla and Microsoft push hosts, because it POSTs to whatever endpoint it stores.

Enable it with --push-contact https://your.site (the NixOS module does this through push.contact).

Access

Nginx must overwrite Remote-User with the Authelia username. Users listed with --editor can log and export. Users listed with --viewer see period days and predictions only. They also see flow and symptoms if the owner turns on sharing in Settings. Everyone else gets 403.

Run locally

python3 app.py --database /tmp/flowtrack.sqlite3 --editor me --dev-user me

Then open http://127.0.0.1:8093.

NixOS module

services.flowtrack = {
  enable = true;
  editors = [ "kayla" ];
  viewers = [ "fred" ];
  backup.directory = "/mnt/disk2/backups/flowtrack";  # nightly, keeps 30
  push.contact = "https://flowtrack.example.org";
  push.time = "*-*-* 09:00:00 Europe/London";
};

python3 app.py --database DB --backup-to DIR --keep N takes a consistent snapshot by hand.